X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fprocfs.c;h=c311ef51c60b11505463c1613e0f8d800c0961c0;hb=c5f62d5ff9f52f2170a401631240af7bf7a850e3;hp=96cdaa9a37d87e0f3e7ed551f0944739223cf816;hpb=0ba6dca974b6df1fc1ac67608815cf5a2603856d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/procfs.c b/gdb/procfs.c index 96cdaa9a37..c311ef51c6 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 + 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,6 +28,8 @@ 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. */ @@ -45,10 +46,13 @@ 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" -/* +/* * PROCFS.C * * This module provides the interface between GDB and the @@ -73,7 +77,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * 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 @@ -82,7 +86,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* 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 @@ -109,90 +113,115 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * 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_fetch_registers (struct target_ops *, + struct regcache *, int); +static void procfs_store_registers (struct target_ops *, + struct regcache *, 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_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 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 (ptid_t); +static int procfs_thread_alive (struct target_ops *ops, ptid_t); -void procfs_find_new_threads (void); -char *procfs_pid_to_str (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 *), +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; -static void -init_procfs_ops (void) + if (endptr == ptr) + return 0; + + 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_notice_signals = procfs_notice_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" =================== */ @@ -206,14 +235,14 @@ init_procfs_ops (void) #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 */ @@ -344,7 +373,7 @@ 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). */ @@ -352,7 +381,7 @@ typedef struct procinfo { /* * 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. */ @@ -377,7 +406,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; @@ -417,7 +446,7 @@ static procinfo * procinfo_list; * Returns: pointer to procinfo, or NULL if not found. */ -static procinfo * +static procinfo * find_procinfo (int pid, int tid) { procinfo *pi; @@ -458,10 +487,10 @@ 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; } @@ -469,14 +498,14 @@ find_procinfo_or_die (int pid, int tid) /* 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) { @@ -523,19 +552,19 @@ 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 + * 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//ctl @@ -553,12 +582,12 @@ open_procinfo_files (procinfo *pi, int which) * 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/ * * 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. @@ -617,11 +646,11 @@ open_procinfo_files (procinfo *pi, int which) * 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. */ @@ -674,7 +703,7 @@ open_procinfo_files (procinfo *pi, int which) 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. */ @@ -751,7 +780,7 @@ destroy_one_procinfo (procinfo **list, procinfo *pi) /* 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) { @@ -825,7 +854,7 @@ dead_procinfo (procinfo *pi, char *msg, int kill_p) kill (pi->pid, SIGKILL); destroy_procinfo (pi); - error (msg); + error ("%s", msg); } /* @@ -849,7 +878,7 @@ sysset_t_size (procinfo * pi) } /* Function: sysset_t_alloc - + Allocate and (partially) initialize a sysset_t struct. */ static sysset_t * @@ -868,7 +897,7 @@ sysset_t_alloc (procinfo * pi) #ifdef DYNAMIC_SYSCALLS /* Function: load_syscalls - + 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 @@ -894,18 +923,18 @@ load_syscalls (procinfo *pi) 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,7 +943,7 @@ 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 @@ -968,13 +997,13 @@ 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 structure. */ @@ -998,7 +1027,7 @@ free_syscalls (procinfo *pi) 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) { @@ -1018,7 +1047,7 @@ 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. * @@ -1118,16 +1147,16 @@ proc_get_status (procinfo *pi) 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)); @@ -1136,7 +1165,7 @@ proc_get_status (procinfo *pi) (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)); @@ -1148,7 +1177,7 @@ proc_get_status (procinfo *pi) 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 @@ -1165,7 +1194,7 @@ 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; } @@ -1178,16 +1207,16 @@ proc_get_status (procinfo *pi) 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 @@ -1198,7 +1227,7 @@ proc_get_status (procinfo *pi) * Function: proc_flags * * returns the process flags (pr_flags field). - */ + */ long proc_flags (procinfo *pi) @@ -1274,7 +1303,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 @@ -1294,7 +1323,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 @@ -1314,7 +1343,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 @@ -1344,9 +1373,9 @@ proc_cursig (struct procinfo *pi) } /* - * 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 * @@ -1368,7 +1397,7 @@ proc_cursig (struct procinfo *pi) * 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. @@ -1383,20 +1412,20 @@ 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 + /* 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 @@ -1463,7 +1492,7 @@ proc_modify_flag (procinfo *pi, long flag, long mode) 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 @@ -1531,7 +1560,7 @@ proc_set_kill_on_last_close (procinfo *pi) * 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. @@ -1581,7 +1610,7 @@ proc_unset_inherit_on_fork (procinfo *pi) * 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. @@ -1614,7 +1643,7 @@ proc_unset_async (procinfo *pi) * 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 @@ -1641,9 +1670,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 @@ -1656,7 +1685,7 @@ proc_stop_process (procinfo *pi) * 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 @@ -1667,10 +1696,10 @@ proc_wait_for_stop (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 + * 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); @@ -1687,9 +1716,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 @@ -1720,7 +1749,7 @@ proc_wait_for_stop (procinfo *pi) * 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 @@ -1733,7 +1762,7 @@ proc_run_process (procinfo *pi, int step, int signo) * 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) { @@ -1773,7 +1802,7 @@ proc_run_process (procinfo *pi, int step, int signo) * 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 @@ -1784,10 +1813,10 @@ proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) /* * 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); @@ -1811,7 +1840,7 @@ proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) pi->status_valid = 0; if (!win) - warning ("procfs: set_traced_signals failed"); + warning (_("procfs: set_traced_signals failed")); return win; } @@ -1819,7 +1848,7 @@ proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) * 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 @@ -1830,10 +1859,10 @@ proc_set_traced_faults (procinfo *pi, fltset_t *fltset) /* * 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); @@ -1863,7 +1892,7 @@ proc_set_traced_faults (procinfo *pi, fltset_t *fltset) * 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 @@ -1874,10 +1903,10 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) /* * 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); @@ -1905,7 +1934,7 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) #endif /* The above operation renders the procinfo's cached pstatus obsolete. */ pi->status_valid = 0; - + return win; } @@ -1913,7 +1942,7 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) * 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 @@ -1924,10 +1953,10 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) /* * 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); @@ -1963,7 +1992,7 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) * 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 @@ -1974,10 +2003,10 @@ proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold) /* * 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); @@ -2017,10 +2046,10 @@ proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save) /* * 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); @@ -2054,10 +2083,10 @@ proc_get_signal_actions (procinfo *pi, gdb_sigaction_t *save) /* * 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); @@ -2091,10 +2120,10 @@ proc_get_held_signals (procinfo *pi, gdb_sigset_t *save) /* * 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); @@ -2137,10 +2166,10 @@ proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save) /* * 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); @@ -2179,10 +2208,10 @@ proc_trace_signal (procinfo *pi, int signo) /* * 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); @@ -2213,10 +2242,10 @@ proc_ignore_signal (procinfo *pi, int signo) /* * 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); @@ -2247,10 +2276,10 @@ proc_get_traced_faults (procinfo *pi, fltset_t *save) /* * 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); @@ -2289,10 +2318,10 @@ proc_get_traced_sysentry (procinfo *pi, sysset_t *save) /* * 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); @@ -2362,10 +2391,10 @@ proc_get_traced_sysexit (procinfo *pi, sysset_t *save) /* * 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); @@ -2435,10 +2464,10 @@ proc_clear_current_fault (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 + * 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); @@ -2476,22 +2505,24 @@ 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 + * 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)) @@ -2499,11 +2530,32 @@ proc_set_current_signal (procinfo *pi, int signo) #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; @@ -2531,10 +2583,10 @@ proc_clear_current_signal (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 + * 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 +2597,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 +2617,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 +2627,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 +2652,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 +2679,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 +2723,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 +2740,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 +2748,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 +2763,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 +2780,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,13 +2801,13 @@ 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; } @@ -2831,10 +2865,10 @@ 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 + * 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); @@ -2852,10 +2886,12 @@ proc_parent_pid (procinfo *pi) 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; } @@ -2867,7 +2903,10 @@ procfs_address_to_host_pointer (CORE_ADDR addr) 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 */ @@ -2878,25 +2917,25 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) 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,7 +2944,7 @@ 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 @@ -2975,11 +3014,11 @@ proc_get_LDT_entry (procinfo *pi, int key) /* 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) { @@ -2997,7 +3036,45 @@ proc_get_LDT_entry (procinfo *pi, int key) #endif } -#endif /* 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. + */ + +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" =============== */ @@ -3007,16 +3084,16 @@ proc_get_LDT_entry (procinfo *pi, int key) 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; @@ -3040,10 +3117,10 @@ proc_get_nthreads (procinfo *pi) 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 @@ -3081,10 +3158,10 @@ 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, + * 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); @@ -3104,7 +3181,7 @@ proc_get_current_thread (procinfo *pi) /* * OSF version */ -int +int proc_get_current_thread (procinfo *pi) { #if 0 /* FIXME: not ready for prime time? */ @@ -3118,7 +3195,7 @@ proc_get_current_thread (procinfo *pi) /* * Default version */ -int +int proc_get_current_thread (procinfo *pi) { return 0; @@ -3128,7 +3205,7 @@ proc_get_current_thread (procinfo *pi) #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). @@ -3165,10 +3242,10 @@ proc_update_threads (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 + * 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); @@ -3220,10 +3297,10 @@ proc_update_threads (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 + * 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); @@ -3232,8 +3309,8 @@ proc_update_threads (procinfo *pi) /* * 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... ;-) @@ -3261,7 +3338,7 @@ proc_update_threads (procinfo *pi) /* * OSF version */ -int +int proc_update_threads (procinfo *pi) { int nthreads, i; @@ -3270,10 +3347,10 @@ proc_update_threads (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 + * 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); @@ -3284,7 +3361,7 @@ proc_update_threads (procinfo *pi) 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__); @@ -3322,8 +3399,8 @@ proc_update_threads (procinfo *pi) * 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 @@ -3344,10 +3421,10 @@ proc_iterate_over_threads (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 + * 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); @@ -3374,6 +3451,17 @@ proc_iterate_over_threads (procinfo *pi, 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 @@ -3504,72 +3592,80 @@ 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"); + 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); } 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); } @@ -3601,7 +3697,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 +3705,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 @@ -3642,7 +3749,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 +3762,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 || - (NPC_REGNUM >= 0 && regno == 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 -} - -/* - * 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. - */ + 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 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 || - (NPC_REGNUM >= 0 && regno == 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__); } @@ -3873,7 +3951,8 @@ syscall_is_lwp_create (procinfo *pi, int scall) */ static ptid_t -procfs_wait (ptid_t ptid, struct target_waitstatus *status) +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; @@ -3917,7 +3996,7 @@ wait_again: 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? */ @@ -3940,7 +4019,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 +4050,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)) { + 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; @@ -4018,7 +4102,7 @@ wait_again: } 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 +4112,9 @@ 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]); } @@ -4059,6 +4143,22 @@ wait_again: 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)) { /* @@ -4078,19 +4178,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); - } + 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 +4199,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 +4214,9 @@ 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 +4232,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 +4246,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 +4257,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; @@ -4185,6 +4279,14 @@ wait_again: #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: @@ -4205,17 +4307,17 @@ wait_again: 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; } /* @@ -4227,29 +4329,14 @@ wait_again: !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)); 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 */ @@ -4258,7 +4345,7 @@ wait_again: printf_filtered ("procfs:%d -- process not stopped.\n", __LINE__); proc_prettyprint_flags (flags, 1); - error ("procfs: ...giving up..."); + error (_("procfs: ...giving up...")); } } @@ -4269,6 +4356,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 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. @@ -4280,7 +4401,7 @@ wait_again: 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; @@ -4327,7 +4448,7 @@ procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, * 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 @@ -4335,7 +4456,7 @@ procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, * 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). */ @@ -4354,19 +4475,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); @@ -4414,10 +4535,10 @@ make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr) * 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. @@ -4425,16 +4546,17 @@ make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr) */ 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 @@ -4463,7 +4585,7 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo) /* 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); @@ -4483,7 +4605,7 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo) 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 @@ -4495,7 +4617,7 @@ 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__); } @@ -4504,7 +4626,7 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo) /* * 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. * @@ -4555,49 +4677,12 @@ procfs_notice_signals (ptid_t ptid) 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", + struct inferior *inf = current_inferior (); + 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_open - * - * A dummy: you don't open procfs. - */ - -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) -{ - /* 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. */ - - return !procfs_suppress_run; -} - /* * Function: target_stop * @@ -4608,16 +4693,16 @@ procfs_can_run (void) */ 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, + * 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. */ @@ -4664,7 +4749,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 @@ -4684,8 +4769,8 @@ unconditionally_kill_inferior (procinfo *pi) * 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)) /* ? */ { @@ -4704,8 +4789,8 @@ procfs_kill_inferior (void) * Forget we ever debugged this thing! */ -static void -procfs_mourn_inferior (void) +static void +procfs_mourn_inferior (struct target_ops *ops) { procinfo *pi; @@ -4716,30 +4801,38 @@ procfs_mourn_inferior (void) 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, + * 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'"); @@ -4795,16 +4888,46 @@ 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); -#ifdef START_INFERIOR_TRAPS_EXPECTED + /* 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)); + + /* 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 } /* @@ -4830,7 +4953,7 @@ 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) { @@ -4914,7 +5037,7 @@ 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 -- + /* FIXME: No need to destroy the procinfo -- we have our own address space, and we're about to do an exec! */ /*destroy_procinfo (pi);*/ } @@ -4923,10 +5046,10 @@ procfs_set_exec_trap (void) * 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 @@ -4935,10 +5058,13 @@ procfs_set_exec_trap (void) */ 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,19 +5127,26 @@ 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); +#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 } /* @@ -5028,7 +5161,7 @@ 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; @@ -5037,12 +5170,12 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr) /* * 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. */ void -procfs_find_new_threads (void) +procfs_find_new_threads (struct target_ops *ops) { procinfo *pi; @@ -5052,7 +5185,7 @@ procfs_find_new_threads (void) proc_iterate_over_threads (pi, procfs_notice_thread, NULL); } -/* +/* * Function: target_thread_alive * * Return true if the thread is still 'alive'. @@ -5062,7 +5195,7 @@ procfs_find_new_threads (void) */ static int -procfs_thread_alive (ptid_t ptid) +procfs_thread_alive (struct target_ops *ops, ptid_t ptid) { int proc, thread; procinfo *pi; @@ -5084,29 +5217,19 @@ procfs_thread_alive (ptid_t ptid) 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; } /* @@ -5114,16 +5237,16 @@ procfs_pid_to_str (ptid_t ptid) * 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 */ @@ -5168,17 +5291,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,13 +5307,13 @@ 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 } /* @@ -5203,13 +5323,12 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) * 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); + pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (!pi) /* If no process, then not stopped by watchpoint! */ return 0; @@ -5217,7 +5336,7 @@ procfs_stopped_by_watchpoint (ptid_t ptid) if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP)) { if (proc_why (pi) == PR_FAULTED) - { + { #ifdef FLTWATCH if (proc_what (pi) == FLTWATCH) return 1; @@ -5231,51 +5350,59 @@ 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. - */ - -struct ssd * -procfs_find_LDT_entry (ptid_t ptid) +static int +procfs_insert_watchpoint (CORE_ADDR addr, int len, int type) { - gdb_gregset_t *gregs; - int key; - procinfo *pi; - - /* Find procinfo for the lwp. */ - if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL) + 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) +{ + 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; } -#endif /* TM_I386SOL2_H */ /* * Memory Mappings Functions: */ -/* +/* * Function: iterate_over_mappings * * Call a callback function once for each mapping, passing it the mapping, @@ -5289,14 +5416,14 @@ procfs_find_LDT_entry (ptid_t ptid) * 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]; @@ -5309,7 +5436,7 @@ 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. */ @@ -5320,7 +5447,7 @@ iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, /* 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__); @@ -5350,10 +5477,10 @@ iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, /* * 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. * @@ -5361,7 +5488,7 @@ iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, * or zero. */ -int solib_mappings_callback (struct prmap *map, +int solib_mappings_callback (struct prmap *map, int (*func) (int, CORE_ADDR), void *data) { @@ -5384,45 +5511,20 @@ int solib_mappings_callback (struct prmap *map, /* 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 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 * @@ -5430,27 +5532,27 @@ proc_iterate_over_mappings (int (*func) (int, CORE_ADDR)) * 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); } @@ -5460,28 +5562,155 @@ find_memory_regions_callback (struct prmap *map, * 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 (target_gdbarch, 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 (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; +} + +/* 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 * @@ -5519,27 +5748,31 @@ mappingflags (long flags) * Callback function, does the actual work for 'info proc mappings'. */ -/* ARGSUSED */ static int info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused) { - char *data_fmt_string; + unsigned int pr_off; - 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"; - - 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; } @@ -5553,23 +5786,24 @@ info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused) 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"); + 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"); @@ -5596,10 +5830,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) { @@ -5626,7 +5858,7 @@ 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. @@ -5634,7 +5866,7 @@ info_proc_cmd (char *args, int from_tty) 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); @@ -5647,17 +5879,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); @@ -5671,68 +5903,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__); - - 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); @@ -5742,20 +5991,18 @@ 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\ + 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" =================== */ @@ -5778,42 +6025,79 @@ procfs_first_available (void) return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1); } +static int +find_signalled_thread (struct thread_info *info, void *data) +{ + if (info->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->stop_signal; + else + return TARGET_SIGNAL_0; +} + /* =================== GCORE .NOTE "MODULE" =================== */ #if defined (UNIXWARE) || defined (PIOCOPENLWP) || defined (PCAGENT) /* 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); + /* 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 (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, &fpregs, sizeof (fpregs)); + + do_cleanups (old_chain); + return note_data; } @@ -5821,6 +6105,7 @@ struct procfs_corefile_thread_data { bfd *obfd; char *note_data; int *note_size; + enum target_signal stop_signal; }; static int @@ -5828,14 +6113,13 @@ 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; } @@ -5852,52 +6136,59 @@ 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 (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; + 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); @@ -5907,7 +6198,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 */