/* Machine independent support for Solaris /proc (process file system) for GDB.
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2020 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#include "regcache.h"
#include "inf-child.h"
#include "nat/fork-inferior.h"
-#include "filestuff.h"
+#include "gdbarch.h"
#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
#include <sys/procfs.h>
#include <sys/fault.h>
#include <sys/syscall.h>
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include <signal.h>
#include <ctype.h>
#include "gdb_bfd.h"
#include "inflow.h"
#include "auxv.h"
#include "procfs.h"
-#include "observer.h"
+#include "observable.h"
+#include "gdbsupport/scoped_fd.h"
+#include "gdbsupport/pathstuff.h"
/* This module provides the interface between GDB and the
/proc file system, which is used on many versions of Unix
/* This module defines the GDB target vector and its methods. */
-static void procfs_attach (struct target_ops *, const char *, int);
-static void procfs_detach (struct target_ops *, const char *, int);
-static void procfs_resume (struct target_ops *,
- ptid_t, int, enum gdb_signal);
-static void procfs_interrupt (struct target_ops *self, ptid_t);
-static void procfs_files_info (struct target_ops *);
-static void procfs_fetch_registers (struct target_ops *,
- struct regcache *, int);
-static void procfs_store_registers (struct target_ops *,
- struct regcache *, int);
-static void procfs_pass_signals (struct target_ops *self,
- int, unsigned char *);
-static void procfs_kill_inferior (struct target_ops *ops);
-static void procfs_mourn_inferior (struct target_ops *ops);
-static void procfs_create_inferior (struct target_ops *, const char *,
- const std::string &, char **, int);
-static ptid_t procfs_wait (struct target_ops *,
- ptid_t, struct target_waitstatus *, int);
+
static enum target_xfer_status procfs_xfer_memory (gdb_byte *,
const gdb_byte *,
ULONGEST, ULONGEST,
ULONGEST *);
-static target_xfer_partial_ftype procfs_xfer_partial;
-static int procfs_thread_alive (struct target_ops *ops, ptid_t);
+class procfs_target final : public inf_child_target
+{
+public:
+ void create_inferior (const char *, const std::string &,
+ char **, int) override;
+
+ void kill () override;
+
+ void mourn_inferior () override;
+
+ void attach (const char *, int) override;
+ void detach (inferior *inf, int) override;
+
+ void resume (ptid_t, int, enum gdb_signal) override;
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ enum target_xfer_status xfer_partial (enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len) override;
+
+ void pass_signals (gdb::array_view<const unsigned char>) override;
+
+ void files_info () override;
+
+ void update_thread_list () override;
+
+ bool thread_alive (ptid_t ptid) override;
+
+ std::string pid_to_str (ptid_t) override;
+
+ char *pid_to_exec_file (int pid) override;
+
+ thread_control_capabilities get_thread_control_capabilities () override
+ { return tc_schedlock; }
+
+ /* find_memory_regions support method for gcore */
+ int find_memory_regions (find_memory_region_ftype func, void *data)
+ override;
+
+ char *make_corefile_notes (bfd *, int *) override;
+
+ bool info_proc (const char *, enum info_proc_what) override;
-static void procfs_update_thread_list (struct target_ops *ops);
-static const char *procfs_pid_to_str (struct target_ops *, ptid_t);
+#if PR_MODEL_NATIVE == PR_MODEL_LP64
+ int auxv_parse (gdb_byte **readptr,
+ gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+ override;
+#endif
+
+ bool stopped_by_watchpoint () override;
+
+ int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+ struct expression *) override;
-static int proc_find_memory_regions (struct target_ops *self,
- find_memory_region_ftype, void *);
+ int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+ struct expression *) override;
-static char *procfs_make_note_section (struct target_ops *self,
- bfd *, int *);
+ int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
-static int procfs_can_use_hw_breakpoint (struct target_ops *self,
- enum bptype, int, int);
+ int can_use_hw_breakpoint (enum bptype, int, int) override;
+ bool stopped_data_address (CORE_ADDR *) override;
+
+ void procfs_init_inferior (int pid);
+};
-static void procfs_info_proc (struct target_ops *, const char *,
- enum info_proc_what);
+static procfs_target the_procfs_target;
-#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+#if 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)
+int
+procfs_target::auxv_parse (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;
}
#endif
-struct target_ops *
-procfs_target (void)
-{
- struct target_ops *t = inf_child_target ();
-
- 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->to_pass_signals = procfs_pass_signals;
- t->to_files_info = procfs_files_info;
- t->to_interrupt = procfs_interrupt;
-
- t->to_update_thread_list = procfs_update_thread_list;
- 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;
- t->to_info_proc = procfs_info_proc;
-
-#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
- t->to_auxv_parse = procfs_auxv_parse;
-#endif
-
- t->to_magic = OPS_MAGIC;
-
- return t;
-}
-
/* =================== END, TARGET_OPS "MODULE" =================== */
-/* World Unification:
-
- Put any typedefs, defines etc. here that are required for the
- unification of code that handles different versions of /proc. */
-
-enum { READ_WATCHFLAG = WA_READ,
- WRITE_WATCHFLAG = WA_WRITE,
- EXEC_WATCHFLAG = WA_EXEC,
- AFTER_WATCHFLAG = WA_TRAPAFTER
-};
-
-
/* =================== STRUCT PROCINFO "MODULE" =================== */
/* FIXME: this comment will soon be out of date W.R.T. threads. */
inferior's procinfo information. */
/* format strings for /proc paths */
-#define MAIN_PROC_NAME_FMT "/proc/%d"
#define CTL_PROC_NAME_FMT "/proc/%d/ctl"
#define AS_PROC_NAME_FMT "/proc/%d/as"
#define MAP_PROC_NAME_FMT "/proc/%d/map"
#define STATUS_PROC_NAME_FMT "/proc/%d/status"
-#define MAX_PROC_NAME_SIZE sizeof("/proc/99999/lwp/8096/lstatus")
+#define MAX_PROC_NAME_SIZE sizeof("/proc/999999/lwp/0123456789/lwpstatus")
typedef struct procinfo {
struct procinfo *next;
static procinfo *find_procinfo (int pid, int tid);
static procinfo *create_procinfo (int pid, int tid);
static void destroy_procinfo (procinfo *p);
-static void do_destroy_procinfo_cleanup (void *);
static void dead_procinfo (procinfo *p, const char *msg, int killp);
static int open_procinfo_files (procinfo *p, int which);
static void close_procinfo_files (procinfo *p);
-static sysset_t *sysset_t_alloc (procinfo *pi);
static int iterate_over_mappings
(procinfo *pi, find_memory_region_ftype child_func, void *data,
several. Here is some rationale:
There are several file descriptors that may need to be open
- for any given process or LWP. The ones we're intereted in are:
+ for any given process or LWP. The ones we're interested in are:
- control (ctl) write-only change the state
- status (status) read-only query the state
- address space (as) read/write access memory
- map (map) read-only virtual addr map
- Most of these are opened lazily as they are needed.
- The pathnames for the 'files' for an LWP look slightly
- different from those of a first-class process:
+ Most of these are opened lazily as they are needed.
+ The pathnames for the 'files' for an LWP look slightly
+ different from those of a first-class process:
Pathnames for a process (<proc-id>):
/proc/<proc-id>/ctl
/proc/<proc-id>/status
Pathnames for an LWP (lwp-id):
/proc/<proc-id>/lwp/<lwp-id>/lwpctl
/proc/<proc-id>/lwp/<lwp-id>/lwpstatus
- An LWP has no map or address space file descriptor, since
- the memory map and address space are shared by all LWPs. */
+ An LWP has no map or address space file descriptor, since
+ the memory map and address space are shared by all LWPs. */
/* In this case, there are several different file descriptors that
we might be asked to open. The control file descriptor will be
{
procinfo *pi, *parent = NULL;
- if ((pi = find_procinfo (pid, tid)))
+ pi = find_procinfo (pid, tid);
+ if (pi != NULL)
return pi; /* Already exists, nothing to do. */
/* Find parent before doing malloc, to save having to cleanup. */
pi->pid = pid;
pi->tid = tid;
- pi->saved_entryset = sysset_t_alloc (pi);
- pi->saved_exitset = sysset_t_alloc (pi);
+ pi->saved_entryset = XNEW (sysset_t);
+ pi->saved_exitset = XNEW (sysset_t);
/* Chain into list. */
if (tid == 0)
{
- sprintf (pi->pathname, MAIN_PROC_NAME_FMT, pid);
+ xsnprintf (pi->pathname, sizeof (pi->pathname), "/proc/%d", pid);
pi->next = procinfo_list;
procinfo_list = pi;
}
else
{
- sprintf (pi->pathname, "/proc/%05d/lwp/%d", pid, tid);
+ xsnprintf (pi->pathname, sizeof (pi->pathname), "/proc/%d/lwp/%d",
+ pid, tid);
pi->next = parent->thread_list;
parent->thread_list = pi;
}
}
}
-static void
-do_destroy_procinfo_cleanup (void *pi)
+/* A deleter that calls destroy_procinfo. */
+struct procinfo_deleter
{
- destroy_procinfo ((procinfo *) pi);
-}
+ void operator() (procinfo *pi) const
+ {
+ destroy_procinfo (pi);
+ }
+};
+
+typedef std::unique_ptr<procinfo, procinfo_deleter> procinfo_up;
enum { NOKILL, KILL };
char procfile[80];
if (pi->pathname)
- {
- print_sys_errmsg (pi->pathname, errno);
- }
+ print_sys_errmsg (pi->pathname, errno);
else
{
- sprintf (procfile, "process %d", pi->pid);
+ xsnprintf (procfile, sizeof (procfile), "process %d", pi->pid);
print_sys_errmsg (procfile, errno);
}
if (kill_p == KILL)
error ("%s", msg);
}
-/* Allocate and (partially) initialize a sysset_t struct. */
-
-static sysset_t *
-sysset_t_alloc (procinfo *pi)
-{
- return (sysset_t *) xmalloc (sizeof (sysset_t));
-}
-
/* =================== END, STRUCT PROCINFO "MODULE" =================== */
-/* =================== /proc "MODULE" =================== */
+/* =================== /proc "MODULE" =================== */
/* This "module" is the interface layer between the /proc system API
and the gdb target vector functions. This layer consists of access
need to use from the /proc API.
The main motivation for this layer is to hide the fact that there
- are two very different implementations of the /proc API. Rather
- than have a bunch of #ifdefs all thru the gdb target vector
- functions, we do our best to hide them all in here. */
+ were two very different implementations of the /proc API. */
static long proc_flags (procinfo *pi);
static int proc_why (procinfo *pi);
static void
proc_warn (procinfo *pi, const char *func, int line)
{
- sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
+ xsnprintf (errmsg, sizeof (errmsg), "procfs: %s line %d, %s",
+ func, line, pi->pathname);
print_sys_errmsg (errmsg, errno);
}
static void
proc_error (procinfo *pi, const char *func, int line)
{
- sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
+ xsnprintf (errmsg, sizeof (errmsg), "procfs: %s line %d, %s",
+ func, line, pi->pathname);
perror_with_name (errmsg);
}
proc_get_status (procinfo *pi)
{
/* Status file descriptor is opened "lazily". */
- if (pi->status_fd == 0 &&
- open_procinfo_files (pi, FD_STATUS) == 0)
+ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0)
{
pi->status_valid = 0;
return 0;
}
/* Reset inherit_on_fork flag. If the process forks a child while we
- are registered for events in the parent, then we will NOT recieve
+ are registered for events in the parent, then we will NOT receive
events from the child. Returns non-zero for success, zero for
failure. */
/* We might conceivably apply this operation to an LWP, and the
LWP's ctl file descriptor might not be open. */
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
return 0;
else
{
procfs_ctl_t cmd = PCWSTOP;
+ set_sigint_trap ();
+
win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
+
+ clear_sigint_trap ();
+
/* We been runnin' and we stopped -- need to update status. */
pi->status_valid = 0;
- clear current signal
- abort the current system call
- stop as soon as finished with system call
- - (ioctl): set traced signal set
- - (ioctl): set held signal set
- - (ioctl): set traced fault set
- - (ioctl): set start pc (vaddr)
Always clears the current fault. PI is the process or LWP to
operate on. If STEP is true, set the process or LWP to trap after
/* We will probably have to apply this operation to individual
threads, so make sure the control file descriptor is open. */
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
- {
- return 0;
- }
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
+ return 0;
runflags = PRCFAULT; /* Always clear current fault. */
if (step)
if (pi->tid != 0)
pi = find_procinfo_or_die (pi->pid, 0);
- struct gdb_proc_ctl_pcsentry {
+ struct {
procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } *argp;
- int argp_size = sizeof (struct gdb_proc_ctl_pcsentry);
-
- argp = (struct gdb_proc_ctl_pcsentry *) xmalloc (argp_size);
+ } arg;
- argp->cmd = PCSENTRY;
- memcpy (&argp->sysset, sysset, sizeof (sysset_t));
+ arg.cmd = PCSENTRY;
+ memcpy (&arg.sysset, sysset, sizeof (sysset_t));
- win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
- xfree (argp);
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
/* The above operation renders the procinfo's cached pstatus
obsolete. */
procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } *argp;
- int argp_size = sizeof (struct gdb_proc_ctl_pcsexit);
-
- argp = (struct gdb_proc_ctl_pcsexit *) xmalloc (argp_size);
+ } arg;
- argp->cmd = PCSEXIT;
- memcpy (&argp->sysset, sysset, sizeof (sysset_t));
+ arg.cmd = PCSEXIT;
+ memcpy (&arg.sysset, sysset, sizeof (sysset_t));
- win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
- xfree (argp);
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
/* The above operation renders the procinfo's cached pstatus
obsolete. */
char sinfo[sizeof (siginfo_t)];
} arg;
siginfo_t mysinfo;
+ process_stratum_target *wait_target;
ptid_t wait_ptid;
struct target_waitstatus wait_status;
pi = find_procinfo_or_die (pi->pid, 0);
/* The pointer is just a type alias. */
- get_last_target_status (&wait_ptid, &wait_status);
- if (ptid_equal (wait_ptid, inferior_ptid)
+ get_last_target_status (&wait_target, &wait_ptid, &wait_status);
+ if (wait_target == &the_procfs_target
+ && wait_ptid == inferior_ptid
&& wait_status.kind == TARGET_WAITKIND_STOPPED
&& wait_status.value.sig == gdb_signal_from_host (signo)
&& proc_get_status (pi)
return 0; /* proc_get_regs has already warned. */
if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
- {
- return 0;
- }
+ return 0;
else
{
struct {
return 0; /* proc_get_fpregs has already warned. */
if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
- {
- return 0;
- }
+ return 0;
else
{
struct {
/* We might conceivably apply this operation to an LWP, and the
LWP's ctl file descriptor might not be open. */
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
- {
- return 0;
- }
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
+ return 0;
else
{
procfs_ctl_t cmd[2];
return (write (pi->ctl_fd, &arg, sizeof (arg)) == sizeof (arg));
}
-#if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
-
-#include <sys/sysi86.h>
-
-/* The KEY is actually the value of the lower 16 bits of the GS
- register for the LWP that we're interested in. Returns the
- matching ssh struct (LDT entry). */
-
-static struct ssd *
-proc_get_LDT_entry (procinfo *pi, int key)
-{
- static struct ssd *ldt_entry = NULL;
- char pathname[MAX_PROC_NAME_SIZE];
- struct cleanup *old_chain = NULL;
- int fd;
-
- /* Allocate space for one LDT entry.
- This alloc must persist, because we return a pointer to it. */
- if (ldt_entry == NULL)
- ldt_entry = XNEW (struct ssd);
-
- /* Open the file descriptor for the LDT table. */
- sprintf (pathname, "/proc/%d/ldt", pi->pid);
- if ((fd = open_with_retry (pathname, O_RDONLY)) < 0)
- {
- proc_warn (pi, "proc_get_LDT_entry (open)", __LINE__);
- return NULL;
- }
- /* Make sure it gets closed again! */
- old_chain = make_cleanup_close (fd);
-
- /* Now 'read' thru the table, find a match and return it. */
- while (read (fd, ldt_entry, sizeof (struct ssd)) == sizeof (struct ssd))
- {
- if (ldt_entry->sel == 0 &&
- ldt_entry->bo == 0 &&
- ldt_entry->acc1 == 0 &&
- ldt_entry->acc2 == 0)
- break; /* end of table */
- /* If key matches, return this entry. */
- if (ldt_entry->sel == key)
- {
- do_cleanups (old_chain);
- return ldt_entry;
- }
- }
- /* Loop ended, match not found. */
- do_cleanups (old_chain);
- return NULL;
-}
-
-/* Returns the pointer to the LDT entry of PTID. */
-
-struct ssd *
-procfs_find_LDT_entry (ptid_t ptid)
-{
- gdb_gregset_t *gregs;
- int key;
- procinfo *pi;
-
- /* Find procinfo for the lwp. */
- if ((pi = find_procinfo (ptid_get_pid (ptid), ptid_get_lwp (ptid))) == NULL)
- {
- warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%ld."),
- ptid_get_pid (ptid), ptid_get_lwp (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."),
- ptid_get_pid (ptid), ptid_get_lwp (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" =============== */
/* =================== Thread "MODULE" =================== */
-/* NOTE: you'll see more ifdefs and duplication of functions here,
- since there is a different way to do threads on every OS. */
-
/* Returns the number of threads for the process. */
static int
return pi->prstatus.pr_nlwp;
}
-/* LWP version.
-
- Return the ID of the thread that had an event of interest.
+/* Return the ID of the thread that had an event of interest.
(ie. the one that hit a breakpoint or other traced event). All
other things being equal, this should be the ID of a thread that is
currently executing. */
}
/* Discover the IDs of all the threads within the process, and create
- a procinfo for each of them (chained to the parent). This
- unfortunately requires a different method on every OS. Returns
+ a procinfo for each of them (chained to the parent). Returns
non-zero for success, zero for failure. */
static int
return 0; /* keep iterating */
}
-static void
-do_closedir_cleanup (void *dir)
-{
- closedir ((DIR *) dir);
-}
-
static int
proc_update_threads (procinfo *pi)
{
char pathname[MAX_PROC_NAME_SIZE + 16];
struct dirent *direntry;
- struct cleanup *old_chain = NULL;
procinfo *thread;
- DIR *dirp;
+ gdb_dir_up dirp;
int lwpid;
/* We should never have to apply this operation to any procinfo
strcpy (pathname, pi->pathname);
strcat (pathname, "/lwp");
- if ((dirp = opendir (pathname)) == NULL)
+ dirp.reset (opendir (pathname));
+ if (dirp == NULL)
proc_error (pi, "update_threads, opendir", __LINE__);
- old_chain = make_cleanup (do_closedir_cleanup, dirp);
- while ((direntry = readdir (dirp)) != NULL)
+ while ((direntry = readdir (dirp.get ())) != NULL)
if (direntry->d_name[0] != '.') /* skip '.' and '..' */
{
lwpid = atoi (&direntry->d_name[0]);
- if ((thread = create_procinfo (pi->pid, lwpid)) == NULL)
+ thread = create_procinfo (pi->pid, lwpid);
+ if (thread == NULL)
proc_error (pi, "update_threads, create_procinfo", __LINE__);
}
pi->threads_valid = 1;
- do_cleanups (old_chain);
return 1;
}
for (thread = pi->thread_list; thread != NULL; thread = next)
{
next = thread->next; /* In case thread is destroyed. */
- if ((retval = (*func) (pi, thread, ptr)) != 0)
+ retval = (*func) (pi, thread, ptr);
+ if (retval != 0)
break;
}
/* Here are all of the gdb target vector functions and their
friends. */
-static ptid_t do_attach (ptid_t ptid);
-static void do_detach (int signo);
+static void do_attach (ptid_t ptid);
+static void do_detach ();
static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
int entry_or_exit, int mode, int from_tty);
/* Register to trace the 'exit' system call (on entry). */
- traced_syscall_entries = sysset_t_alloc (pi);
+ traced_syscall_entries = XNEW (sysset_t);
premptyset (traced_syscall_entries);
praddset (traced_syscall_entries, SYS_exit);
praddset (traced_syscall_entries, SYS_lwp_exit);
return __LINE__;
/* Method for tracing exec syscalls. */
- /* GW: Rationale...
- Not all systems with /proc have all the exec* syscalls with the same
- names. On the SGI, for example, there is no SYS_exec, but there
- *is* a SYS_execv. So, we try to account for that. */
-
- traced_syscall_exits = sysset_t_alloc (pi);
+ traced_syscall_exits = XNEW (sysset_t);
premptyset (traced_syscall_exits);
-#ifdef SYS_exec
- praddset (traced_syscall_exits, SYS_exec);
-#endif
praddset (traced_syscall_exits, SYS_execve);
praddset (traced_syscall_exits, SYS_lwp_create);
praddset (traced_syscall_exits, SYS_lwp_exit);
return 0;
}
-static void
-procfs_attach (struct target_ops *ops, const char *args, int from_tty)
+void
+procfs_target::attach (const char *args, int from_tty)
{
- char *exec_file;
int pid;
pid = parse_pid_to_attach (args);
if (from_tty)
{
- exec_file = get_exec_file (0);
+ const char *exec_file = get_exec_file (0);
if (exec_file)
printf_filtered (_("Attaching to program `%s', %s\n"),
- exec_file, target_pid_to_str (pid_to_ptid (pid)));
+ exec_file, target_pid_to_str (ptid_t (pid)).c_str ());
else
printf_filtered (_("Attaching to %s\n"),
- target_pid_to_str (pid_to_ptid (pid)));
+ target_pid_to_str (ptid_t (pid)).c_str ());
fflush (stdout);
}
- inferior_ptid = do_attach (pid_to_ptid (pid));
- if (!target_is_pushed (ops))
- push_target (ops);
+ do_attach (ptid_t (pid));
+ if (!target_is_pushed (this))
+ push_target (this);
}
-static void
-procfs_detach (struct target_ops *ops, const char *args, int from_tty)
+void
+procfs_target::detach (inferior *inf, int from_tty)
{
- int sig = 0;
- int pid = ptid_get_pid (inferior_ptid);
-
- if (args)
- sig = atoi (args);
+ int pid = inferior_ptid.pid ();
if (from_tty)
{
exec_file = "";
printf_filtered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
- gdb_flush (gdb_stdout);
+ target_pid_to_str (ptid_t (pid)).c_str ());
}
- do_detach (sig);
+ do_detach ();
- inferior_ptid = null_ptid;
- detach_inferior (pid);
- inf_child_maybe_unpush_target (ops);
+ switch_to_no_thread ();
+ detach_inferior (inf);
+ maybe_unpush_target ();
}
-static ptid_t
+static void
do_attach (ptid_t ptid)
{
procinfo *pi;
int fail;
int lwpid;
- if ((pi = create_procinfo (ptid_get_pid (ptid), 0)) == NULL)
+ pi = create_procinfo (ptid.pid (), 0);
+ if (pi == NULL)
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",
- ptid_get_pid (ptid));
+ xsnprintf (errmsg, sizeof (errmsg),
+ "do_attach: couldn't open /proc file for process %d",
+ ptid.pid ());
dead_procinfo (pi, errmsg, NOKILL);
}
if (!proc_get_held_signals (pi, &pi->saved_sighold))
dead_procinfo (pi, "do_attach: couldn't save held signals.", NOKILL);
- if ((fail = procfs_debug_inferior (pi)) != 0)
+ fail = procfs_debug_inferior (pi);
+ if (fail != 0)
dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL);
inf = current_inferior ();
create_procinfo (pi->pid, lwpid);
/* Add it to gdb's thread list. */
- ptid = ptid_build (pi->pid, lwpid, 0);
- add_thread (ptid);
-
- return ptid;
+ ptid = ptid_t (pi->pid, lwpid, 0);
+ thread_info *thr = add_thread (&the_procfs_target, ptid);
+ switch_to_thread (thr);
}
static void
-do_detach (int signo)
+do_detach ()
{
procinfo *pi;
/* Find procinfo for the main process. */
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid),
+ pi = find_procinfo_or_die (inferior_ptid.pid (),
0); /* FIXME: threads */
- if (signo)
- if (!proc_set_current_signal (pi, signo))
- proc_warn (pi, "do_detach, set_current_signal", __LINE__);
if (!proc_set_traced_signals (pi, &pi->saved_sigset))
proc_warn (pi, "do_detach, set_traced_signal", __LINE__);
if (!proc_set_held_signals (pi, &pi->saved_sighold))
proc_warn (pi, "do_detach, set_held_signals", __LINE__);
- if (signo || (proc_flags (pi) & (PR_STOPPED | PR_ISTOP)))
- if (signo || !(pi->was_stopped) ||
- query (_("Was stopped when attached, make it runnable again? ")))
+ if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
+ if (!(pi->was_stopped)
+ || query (_("Was stopped when attached, make it runnable again? ")))
{
/* Clear any pending signal. */
if (!proc_clear_current_fault (pi))
proc_warn (pi, "do_detach, clear_current_fault", __LINE__);
- if (signo == 0 && !proc_clear_current_signal (pi))
+ if (!proc_clear_current_signal (pi))
proc_warn (pi, "do_detach, clear_current_signal", __LINE__);
if (!proc_set_run_on_last_close (pi))
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers.
- ??? Is the following note still relevant? We can't get individual
- registers with the PT_GETREGS ptrace(2) request either, yet we
- don't bother with caching at all in that case.
-
NOTE: Since the /proc interface cannot give us individual
registers, we pay no attention to REGNUM, and just fetch them all.
This results in the possibility that we will do unnecessarily many
registers. So we cache the results, and mark the cache invalid
when the process is resumed. */
-static void
-procfs_fetch_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum)
+void
+procfs_target::fetch_registers (struct regcache *regcache, int regnum)
{
gdb_gregset_t *gregs;
procinfo *pi;
- ptid_t ptid = regcache_get_ptid (regcache);
- int pid = ptid_get_pid (ptid);
- int tid = ptid_get_lwp (ptid);
+ ptid_t ptid = regcache->ptid ();
+ int pid = ptid.pid ();
+ int tid = ptid.lwp ();
struct gdbarch *gdbarch = regcache->arch ();
pi = find_procinfo_or_die (pid, tid);
if (pi == NULL)
error (_("procfs: fetch_registers failed to find procinfo for %s"),
- target_pid_to_str (ptid));
+ target_pid_to_str (ptid).c_str ());
gregs = proc_get_gregs (pi);
if (gregs == NULL)
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 (struct target_ops *ops,
- struct regcache *regcache, int regnum)
+void
+procfs_target::store_registers (struct regcache *regcache, int regnum)
{
gdb_gregset_t *gregs;
procinfo *pi;
- ptid_t ptid = regcache_get_ptid (regcache);
- int pid = ptid_get_pid (ptid);
- int tid = ptid_get_lwp (ptid);
+ ptid_t ptid = regcache->ptid ();
+ int pid = ptid.pid ();
+ int tid = ptid.lwp ();
struct gdbarch *gdbarch = regcache->arch ();
pi = find_procinfo_or_die (pid, tid);
if (pi == NULL)
error (_("procfs: store_registers: failed to find procinfo for %s"),
- target_pid_to_str (ptid));
+ target_pid_to_str (ptid).c_str ());
gregs = proc_get_gregs (pi);
if (gregs == NULL)
}
}
-static int
-syscall_is_lwp_exit (procinfo *pi, int scall)
-{
- if (scall == SYS_lwp_exit)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_exit (procinfo *pi, int scall)
-{
- if (scall == SYS_exit)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_exec (procinfo *pi, int scall)
-{
-#ifdef SYS_exec
- if (scall == SYS_exec)
- return 1;
-#endif
- if (scall == SYS_execve)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_lwp_create (procinfo *pi, int scall)
-{
- if (scall == SYS_lwp_create)
- return 1;
- return 0;
-}
-
/* Retrieve the next stop event from the child process. If child has
not stopped yet, wait for it to stop. Translate /proc eventcodes
(or possibly wait eventcodes) into gdb internal event codes.
Returns the id of process (and possibly thread) that incurred the
event. Event codes are returned through a pointer parameter. */
-static ptid_t
-procfs_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+procfs_target::wait (ptid_t ptid, struct target_waitstatus *status,
+ int options)
{
/* First cut: loosely based on original version 2.1. */
procinfo *pi;
retry++;
wstat = 0;
- retval = pid_to_ptid (-1);
+ retval = ptid_t (-1);
/* Find procinfo for main process. */
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+
+ /* procfs_target currently only supports one inferior. */
+ inferior *inf = current_inferior ();
+
+ pi = find_procinfo_or_die (inf->pid, 0);
if (pi)
{
/* We must assume that the status is stale now... */
pi->status_valid = 0; /* re-read again, IMMEDIATELY... */
#endif
/* If child is not stopped, wait for it to stop. */
- if (!(proc_flags (pi) & (PR_STOPPED | PR_ISTOP)) &&
- !proc_wait_for_stop (pi))
+ if (!(proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
+ && !proc_wait_for_stop (pi))
{
/* wait_for_stop failed: has the child terminated? */
if (errno == ENOENT)
int wait_retval;
/* /proc file not found; presumably child has terminated. */
- wait_retval = wait (&wstat); /* "wait" for the child's exit. */
+ wait_retval = ::wait (&wstat); /* "wait" for the child's exit. */
/* Wrong child? */
- if (wait_retval != ptid_get_pid (inferior_ptid))
+ if (wait_retval != inf->pid)
error (_("procfs: couldn't stop "
"process %d: wait returned %d."),
- ptid_get_pid (inferior_ptid), wait_retval);
+ inf->pid, wait_retval);
/* FIXME: might I not just use waitpid?
Or try find_procinfo to see if I know about this child? */
- retval = pid_to_ptid (wait_retval);
+ retval = ptid_t (wait_retval);
}
else if (errno == EINTR)
goto wait_again;
/* The 'pid' we will return to GDB is composed of
the process ID plus the lwp ID. */
- retval = ptid_build (pi->pid, proc_get_current_thread (pi), 0);
+ retval = ptid_t (pi->pid, proc_get_current_thread (pi), 0);
switch (why) {
case PR_SIGNALLED:
wstat = (what << 8) | 0177;
break;
case PR_SYSENTRY:
- if (syscall_is_lwp_exit (pi, what))
+ if (what == SYS_lwp_exit)
{
if (print_thread_events)
printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (retval));
- delete_thread (retval);
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return retval;
+ target_pid_to_str (retval).c_str ());
+ delete_thread (find_thread_ptid (this, retval));
+ target_continue_no_signal (ptid);
+ goto wait_again;
}
- else if (syscall_is_exit (pi, what))
+ else if (what == SYS_exit)
{
- struct inferior *inf;
-
/* Handle SYS_exit call only. */
/* Stopped at entry to SYS_exit.
Make it runnable, resume it, then use
if (!proc_run_process (pi, 0, 0))
proc_error (pi, "target_wait, run_process", __LINE__);
- inf = find_inferior_pid (pi->pid);
if (inf->attach_flag)
{
/* Don't call wait: simulate waiting for exit,
return a "success" exit code. Bogus: what if
it returns something else? */
wstat = 0;
- retval = inferior_ptid; /* ? ? ? */
+ retval = ptid_t (inf->pid); /* ? ? ? */
}
else
{
- int temp = wait (&wstat);
+ int temp = ::wait (&wstat);
/* FIXME: shouldn't I make sure I get the right
event from the right process? If (for
/* If wait returns -1, that's what we return
to GDB. */
if (temp < 0)
- retval = pid_to_ptid (temp);
+ retval = ptid_t (temp);
}
}
else
long i, nsysargs, *sysargs;
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ nsysargs = proc_nsysarg (pi);
+ sysargs = proc_sysargs (pi);
+
+ if (nsysargs > 0 && sysargs != NULL)
{
printf_filtered (_("%ld syscall arguments:\n"),
nsysargs);
i, sysargs[i]);
}
- if (status)
- {
- /* How to exit gracefully, returning "unknown
- event". */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_ptid;
- }
- else
- {
- /* How to keep going without returning to wfi: */
- target_continue_no_signal (ptid);
- goto wait_again;
- }
+ /* How to keep going without returning to wfi: */
+ target_continue_no_signal (ptid);
+ goto wait_again;
}
break;
case PR_SYSEXIT:
- if (syscall_is_exec (pi, what))
+ if (what == SYS_execve)
{
/* Hopefully this is our own "fork-child" execing
the real child. Hoax this event into a trap, and
address. */
wstat = (SIGTRAP << 8) | 0177;
}
- else if (syscall_is_lwp_create (pi, what))
+ else if (what == SYS_lwp_create)
{
/* This syscall is somewhat like fork/exec. We
will get the event twice: once for the parent
if (!find_procinfo (pi->pid, temp_tid))
create_procinfo (pi->pid, temp_tid);
- temp_ptid = ptid_build (pi->pid, temp_tid, 0);
+ temp_ptid = ptid_t (pi->pid, temp_tid, 0);
/* If not in GDB's thread list, add it. */
- if (!in_thread_list (temp_ptid))
- add_thread (temp_ptid);
+ if (!in_thread_list (this, temp_ptid))
+ add_thread (this, temp_ptid);
- /* Return to WFI, but tell it to immediately resume. */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_ptid;
+ target_continue_no_signal (ptid);
+ goto wait_again;
}
- else if (syscall_is_lwp_exit (pi, what))
+ else if (what == SYS_lwp_exit)
{
if (print_thread_events)
printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (retval));
- delete_thread (retval);
+ target_pid_to_str (retval).c_str ());
+ delete_thread (find_thread_ptid (this, retval));
status->kind = TARGET_WAITKIND_SPURIOUS;
return retval;
}
- else if (0)
- {
- /* FIXME: Do we need to handle SYS_sproc,
- SYS_fork, or SYS_vfork here? The old procfs
- seemed to use this event to handle threads on
- older (non-LWP) systems, where I'm assuming
- that threads were actually separate processes.
- Irix, maybe? Anyway, low priority for now. */
- }
else
{
printf_filtered (_("procfs: trapped on exit from "));
long i, nsysargs, *sysargs;
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ nsysargs = proc_nsysarg (pi);
+ sysargs = proc_sysargs (pi);
+
+ if (nsysargs > 0 && sysargs != NULL)
{
printf_filtered (_("%ld syscall arguments:\n"),
nsysargs);
i, sysargs[i]);
}
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_ptid;
+ target_continue_no_signal (ptid);
+ goto wait_again;
}
break;
case PR_REQUESTED:
create_procinfo (pi->pid, temp_tid);
/* If not in GDB's thread list, add it. */
- temp_ptid = ptid_build (pi->pid, temp_tid, 0);
- if (!in_thread_list (temp_ptid))
- add_thread (temp_ptid);
+ temp_ptid = ptid_t (pi->pid, temp_tid, 0);
+ if (!in_thread_list (this, temp_ptid))
+ add_thread (this, temp_ptid);
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = GDB_SIGNAL_0;
wstat = (what << 8) | 0177;
break;
case PR_FAULTED:
- switch (what) {
- case FLTWATCH:
- wstat = (SIGTRAP << 8) | 0177;
- break;
- /* FIXME: use si_signo where possible. */
- case FLTPRIV:
- case FLTILL:
- wstat = (SIGILL << 8) | 0177;
- break;
- case FLTBPT:
- case FLTTRACE:
- wstat = (SIGTRAP << 8) | 0177;
- break;
- case FLTSTACK:
- case FLTACCESS:
- case FLTBOUNDS:
- wstat = (SIGSEGV << 8) | 0177;
- break;
- case FLTIOVF:
- case FLTIZDIV:
- case FLTFPE:
- wstat = (SIGFPE << 8) | 0177;
- break;
- case FLTPAGE: /* Recoverable page fault */
- default: /* FIXME: use si_signo if possible for
- fault. */
- retval = pid_to_ptid (-1);
- printf_filtered ("procfs:%d -- ", __LINE__);
- printf_filtered (_("child stopped for unknown reason:\n"));
- proc_prettyprint_why (why, what, 1);
- error (_("... giving up..."));
- break;
+ {
+ int signo = pi->prstatus.pr_lwp.pr_info.si_signo;
+ if (signo != 0)
+ wstat = (signo << 8) | 0177;
}
- break; /* case PR_FAULTED: */
+ break;
default: /* switch (why) unmatched */
printf_filtered ("procfs:%d -- ", __LINE__);
printf_filtered (_("child stopped for unknown reason:\n"));
}
/* Got this far without error: If retval isn't in the
threads database, add it. */
- if (ptid_get_pid (retval) > 0 &&
- !ptid_equal (retval, inferior_ptid) &&
- !in_thread_list (retval))
+ if (retval.pid () > 0
+ && !in_thread_list (this, retval))
{
/* We have a new thread. We need to add it both to
GDB's list and to our own. If we don't create a
procinfo, resume may be unhappy later. */
- add_thread (retval);
- if (find_procinfo (ptid_get_pid (retval),
- ptid_get_lwp (retval)) == NULL)
- create_procinfo (ptid_get_pid (retval),
- ptid_get_lwp (retval));
+ add_thread (this, retval);
+ if (find_procinfo (retval.pid (),
+ retval.lwp ()) == NULL)
+ create_procinfo (retval.pid (),
+ retval.lwp ());
}
}
else /* Flags do not indicate STOPPED. */
/* Perform a partial transfer to/from the specified object. For
memory transfers, fall back to the old memory xfer functions. */
-static enum target_xfer_status
-procfs_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len)
+enum target_xfer_status
+procfs_target::xfer_partial (enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset,
+ ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
case TARGET_OBJECT_AUXV:
- return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
+ return memory_xfer_auxv (this, object, annex, readbuf, writebuf,
offset, len, xfered_len);
default:
- return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
+ return this->beneath ()->xfer_partial (object, annex,
+ readbuf, writebuf, offset, len,
+ xfered_len);
}
}
int nbytes;
/* Find procinfo for main process. */
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
- if (pi->as_fd == 0 &&
- open_procinfo_files (pi, FD_AS) == 0)
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
+ if (pi->as_fd == 0 && open_procinfo_files (pi, FD_AS) == 0)
{
proc_warn (pi, "xfer_memory, open_proc_files", __LINE__);
return TARGET_XFER_E_IO;
File descriptors are also cached. As they are a limited resource,
we cannot hold onto them indefinitely. However, as they are
expensive to open, we don't want to throw them away
- indescriminately either. As a compromise, we will keep the file
+ indiscriminately either. As a compromise, we will keep the file
descriptors for the parent process, but discard any file
descriptors we may have accumulated for the threads.
/* About to run the child; invalidate caches and do any other
cleanup. */
-#if 0
- if (pi->gregs_dirty)
- if (parent == NULL ||
- proc_get_current_thread (parent) != pi->tid)
- if (!proc_set_gregs (pi)) /* flush gregs cache */
- proc_warn (pi, "target_resume, set_gregs",
- __LINE__);
- 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",
- __LINE__);
-#endif
-
if (parent != NULL)
{
/* The presence of a parent indicates that this is an LWP.
}
pi->gregs_valid = 0;
pi->fpregs_valid = 0;
-#if 0
- pi->gregs_dirty = 0;
- pi->fpregs_dirty = 0;
-#endif
pi->status_valid = 0;
pi->threads_valid = 0;
return 0;
}
-#if 0
-/* A callback function for iterate_over_threads. Find the
- asynchronous signal thread, and make it runnable. See if that
- helps matters any. */
-
-static int
-make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr)
-{
-#ifdef PR_ASLWP
- if (proc_flags (pi) & PR_ASLWP)
- {
- if (!proc_run_process (pi, 0, -1))
- proc_error (pi, "make_signal_thread_runnable", __LINE__);
- return 1;
- }
-#endif
- return 0;
-}
-#endif
-
/* Make the child process runnable. Normally we will then call
procfs_wait and wait for it to stop again (unless gdb is async).
allow any child thread to run; if non-zero, then allow only the
indicated thread to run. (not implemented yet). */
-static void
-procfs_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal signo)
+void
+procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
procinfo *pi, *thread;
int native_signo;
- /* 2.1:
- prrun.prflags |= PRSVADDR;
- 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 |= PRCFAULT; clear current fault.
-
- PRSTRACE and PRSFAULT can be done by other means
- (proc_trace_signals, proc_trace_faults)
- PRSVADDR is unnecessary.
- PRCFAULT may be replaced by a PIOCCFAULT call (proc_clear_current_fault)
+ /* FIXME: Check/reword. */
+
+ /* prrun.prflags |= PRCFAULT; clear current fault.
+ PRCFAULT may be replaced by a PCCFAULT call (proc_clear_current_fault)
This basically leaves PRSTEP and PRCSIG.
- PRCSIG is like PIOCSSIG (proc_clear_current_signal).
+ PRCSIG is like PCSSIG (proc_clear_current_signal).
So basically PR_STEP is the sole argument that must be passed
- to proc_run_process (for use in the prrun struct by ioctl). */
+ to proc_run_process. */
/* Find procinfo for main process. */
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
/* First cut: ignore pid argument. */
errno = 0;
/* Convert signal to host numbering. */
- if (signo == 0 ||
- (signo == GDB_SIGNAL_STOP && pi->ignore_next_sigstop))
+ if (signo == 0 || (signo == GDB_SIGNAL_STOP && pi->ignore_next_sigstop))
native_signo = 0;
else
native_signo = gdb_signal_to_host (signo);
/* Void the process procinfo's caches. */
invalidate_cache (NULL, pi, NULL);
- if (ptid_get_pid (ptid) != -1)
+ if (ptid.pid () != -1)
{
/* Resume a specific thread, presumably suppressing the
others. */
- thread = find_procinfo (ptid_get_pid (ptid), ptid_get_lwp (ptid));
+ thread = find_procinfo (ptid.pid (), ptid.lwp ());
if (thread != NULL)
{
if (thread->tid != 0)
others. Set the child process's PR_ASYNC flag. */
if (!proc_set_async (pi))
proc_error (pi, "target_resume, set_async", __LINE__);
-#if 0
- proc_iterate_over_threads (pi,
- make_signal_thread_runnable,
- NULL);
-#endif
pi = thread; /* Substitute the thread's procinfo
for run. */
}
/* Set up to trace signals in the child process. */
-static void
-procfs_pass_signals (struct target_ops *self,
- int numsigs, unsigned char *pass_signals)
+void
+procfs_target::pass_signals (gdb::array_view<const unsigned char> pass_signals)
{
sigset_t signals;
- procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
int signo;
prfillset (&signals);
for (signo = 0; signo < NSIG; signo++)
{
int target_signo = gdb_signal_from_host (signo);
- if (target_signo < numsigs && pass_signals[target_signo])
+ if (target_signo < pass_signals.size () && pass_signals[target_signo])
prdelset (&signals, signo);
}
/* Print status information about the child process. */
-static void
-procfs_files_info (struct target_ops *ignore)
+void
+procfs_target::files_info ()
{
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));
-}
-
-/* Stop the child process asynchronously, as when the gdb user types
- control-c or presses a "stop" button. Works by sending
- kill(SIGINT) to the child's process group. */
-
-static void
-procfs_interrupt (struct target_ops *self, ptid_t ptid)
-{
- kill (-inferior_process_group (), SIGINT);
+ target_pid_to_str (inferior_ptid).c_str ());
}
/* Make it die. Wait for it to die. Clean up after it. Note: this
/* We're done debugging it, and we want it to go away. Then we want
GDB to forget all about it. */
-static void
-procfs_kill_inferior (struct target_ops *ops)
+void
+procfs_target::kill ()
{
- if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
+ if (inferior_ptid != null_ptid) /* ? */
{
/* Find procinfo for main process. */
- procinfo *pi = find_procinfo (ptid_get_pid (inferior_ptid), 0);
+ procinfo *pi = find_procinfo (inferior_ptid.pid (), 0);
if (pi)
unconditionally_kill_inferior (pi);
/* Forget we ever debugged this thing! */
-static void
-procfs_mourn_inferior (struct target_ops *ops)
+void
+procfs_target::mourn_inferior ()
{
procinfo *pi;
- if (!ptid_equal (inferior_ptid, null_ptid))
+ if (inferior_ptid != null_ptid)
{
/* Find procinfo for main process. */
- pi = find_procinfo (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo (inferior_ptid.pid (), 0);
if (pi)
destroy_procinfo (pi);
}
generic_mourn_inferior ();
- inf_child_maybe_unpush_target (ops);
+ maybe_unpush_target ();
}
/* When GDB forks to create a runnable inferior process, this function
whatever is necessary to make the child ready to be debugged, and
then wait for the child to synchronize. */
-static void
-procfs_init_inferior (struct target_ops *ops, int pid)
+void
+procfs_target::procfs_init_inferior (int pid)
{
procinfo *pi;
- sigset_t signals;
int fail;
int lwpid;
- /* This routine called on the parent side (GDB side)
- after GDB forks the inferior. */
- if (!target_is_pushed (ops))
- push_target (ops);
-
- if ((pi = create_procinfo (pid, 0)) == NULL)
+ pi = create_procinfo (pid, 0);
+ if (pi == NULL)
perror (_("procfs: out of memory in 'init_inferior'"));
if (!open_procinfo_files (pi, FD_CTL))
procfs_notice_signals
prfillset (fault)
prdelset (FLTPAGE)
- PIOCWSTOP
- PIOCSFAULT
*/
/* If not stopped yet, wait for it to stop. */
- if (!(proc_flags (pi) & PR_STOPPED) &&
- !(proc_wait_for_stop (pi)))
+ if (!(proc_flags (pi) & PR_STOPPED) && !(proc_wait_for_stop (pi)))
dead_procinfo (pi, "init_inferior: wait_for_stop failed", KILL);
/* Save some of the /proc state to be restored if we detach. */
if (!proc_get_traced_sysexit (pi, pi->saved_exitset))
proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__);
- if ((fail = procfs_debug_inferior (pi)) != 0)
+ fail = procfs_debug_inferior (pi);
+ if (fail != 0)
proc_error (pi, "init_inferior (procfs_debug_inferior)", fail);
/* FIXME: logically, we should really be turning OFF run-on-last-close,
/* 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),
- ptid_build (pid, lwpid, 0));
+ thread_change_ptid (this, ptid_t (pid), ptid_t (pid, lwpid, 0));
gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
}
procinfo *pi;
sysset_t *exitset;
- if ((pi = create_procinfo (getpid (), 0)) == NULL)
+ pi = create_procinfo (getpid (), 0);
+ if (pi == NULL)
perror_with_name (_("procfs: create_procinfo failed in child."));
if (open_procinfo_files (pi, FD_CTL) == 0)
_exit (127);
}
- /* Method for tracing exec syscalls. */
- /* GW: Rationale...
- Not all systems with /proc have all the exec* syscalls with the same
- names. On the SGI, for example, there is no SYS_exec, but there
- *is* a SYS_execv. So, we try to account for that. */
-
- exitset = sysset_t_alloc (pi);
+ exitset = XNEW (sysset_t);
premptyset (exitset);
-#ifdef SYS_exec
- praddset (exitset, SYS_exec);
-#endif
praddset (exitset, SYS_execve);
if (!proc_set_traced_sysexit (pi, exitset))
/*destroy_procinfo (pi);*/
}
+/* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2).
+ This avoids a possible deadlock gdb and its vfork'ed child. */
+static void
+procfs_pre_trace (void)
+{
+}
+
/* This function is called BEFORE gdb forks the inferior process. Its
only real responsibility is to set things up for the fork, and tell
GDB which two functions to call after the fork (one for the parent,
abstracted out and shared with other unix targets such as
inf-ptrace? */
-static void
-procfs_create_inferior (struct target_ops *ops, const char *exec_file,
- const std::string &allargs, char **env, int from_tty)
+void
+procfs_target::create_inferior (const char *exec_file,
+ const std::string &allargs,
+ char **env, int from_tty)
{
- char *shell_file = getenv ("SHELL");
+ const char *shell_file = get_shell ();
char *tryname;
int pid;
- if (shell_file != NULL && strchr (shell_file, '/') == NULL)
+ if (strchr (shell_file, '/') == NULL)
{
/* We will be looking down the PATH to find shell_file. If we
shell_file = tryname;
}
+ if (!target_is_pushed (this))
+ push_target (this);
+
pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
- NULL, NULL, shell_file, NULL);
+ NULL, procfs_pre_trace, shell_file, NULL);
/* We have something that executes now. We'll be running through
the shell at this point (if startup-with-shell is true), but the
pid shouldn't change. */
- add_thread_silent (pid_to_ptid (pid));
+ thread_info *thr = add_thread_silent (this, ptid_t (pid));
+ switch_to_thread (thr);
- procfs_init_inferior (ops, pid);
+ procfs_init_inferior (pid);
}
/* An observer for the "inferior_created" event. */
static int
procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
{
- ptid_t gdb_threadid = ptid_build (pi->pid, thread->tid, 0);
+ ptid_t gdb_threadid = ptid_t (pi->pid, thread->tid, 0);
- if (!in_thread_list (gdb_threadid) || is_exited (gdb_threadid))
- add_thread (gdb_threadid);
+ thread_info *thr = find_thread_ptid (&the_procfs_target, gdb_threadid);
+ if (thr == NULL || thr->state == THREAD_EXITED)
+ add_thread (&the_procfs_target, gdb_threadid);
return 0;
}
/* Query all the threads that the target knows about, and give them
back to GDB to add to its list. */
-static void
-procfs_update_thread_list (struct target_ops *ops)
+void
+procfs_target::update_thread_list ()
{
procinfo *pi;
prune_threads ();
/* Find procinfo for main process. */
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
proc_update_threads (pi);
proc_iterate_over_threads (pi, procfs_notice_thread, NULL);
}
really seem to be doing his job. Got to investigate how to tell
when a thread is really gone. */
-static int
-procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+procfs_target::thread_alive (ptid_t ptid)
{
int proc, thread;
procinfo *pi;
- proc = ptid_get_pid (ptid);
- thread = ptid_get_lwp (ptid);
+ proc = ptid.pid ();
+ thread = ptid.lwp ();
/* If I don't know it, it ain't alive! */
- if ((pi = find_procinfo (proc, thread)) == NULL)
- return 0;
+ pi = find_procinfo (proc, thread);
+ if (pi == NULL)
+ return false;
/* If I can't get its status, it ain't alive!
What's more, I need to forget about it! */
if (!proc_get_status (pi))
{
destroy_procinfo (pi);
- return 0;
+ return false;
}
/* I couldn't have got its status if it weren't alive, so it's
alive. */
- return 1;
+ return true;
}
-/* Convert PTID to a string. Returns the string in a static
- buffer. */
+/* Convert PTID to a string. */
-static const char *
-procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
+std::string
+procfs_target::pid_to_str (ptid_t ptid)
{
- static char buf[80];
-
- if (ptid_get_lwp (ptid) == 0)
- sprintf (buf, "process %d", ptid_get_pid (ptid));
+ if (ptid.lwp () == 0)
+ return string_printf ("process %d", ptid.pid ());
else
- sprintf (buf, "LWP %ld", ptid_get_lwp (ptid));
+ return string_printf ("LWP %ld", ptid.lwp ());
+}
+
+/* Accepts an integer PID; Returns a string representing a file that
+ can be opened to get the symbols for the child process. */
+
+char *
+procfs_target::pid_to_exec_file (int pid)
+{
+ static char buf[PATH_MAX];
+ char name[PATH_MAX];
+
+ /* Solaris 11 introduced /proc/<proc-id>/execname. */
+ xsnprintf (name, sizeof (name), "/proc/%d/execname", pid);
+ scoped_fd fd (gdb_open_cloexec (name, O_RDONLY, 0));
+ if (fd.get () < 0 || read (fd.get (), buf, PATH_MAX - 1) < 0)
+ {
+ /* If that fails, fall back to /proc/<proc-id>/path/a.out introduced in
+ Solaris 10. */
+ ssize_t len;
+
+ xsnprintf (name, sizeof (name), "/proc/%d/path/a.out", pid);
+ len = readlink (name, buf, PATH_MAX - 1);
+ if (len <= 0)
+ strcpy (buf, name);
+ else
+ buf[len] = '\0';
+ }
return buf;
}
int pflags = 0;
procinfo *pi;
- pi = find_procinfo_or_die (ptid_get_pid (ptid) == -1 ?
- ptid_get_pid (inferior_ptid) : ptid_get_pid (ptid),
+ pi = find_procinfo_or_die (ptid.pid () == -1 ?
+ inferior_ptid.pid () : ptid.pid (),
0);
/* Translate from GDB's flags to /proc's. */
{
switch (rwflag) { /* FIXME: need an enum! */
case hw_write: /* default watchpoint (write) */
- pflags = WRITE_WATCHFLAG;
+ pflags = WA_WRITE;
break;
case hw_read: /* read watchpoint */
- pflags = READ_WATCHFLAG;
+ pflags = WA_READ;
break;
case hw_access: /* access watchpoint */
- pflags = READ_WATCHFLAG | WRITE_WATCHFLAG;
+ pflags = WA_READ | WA_WRITE;
break;
case hw_execute: /* execution HW breakpoint */
- pflags = EXEC_WATCHFLAG;
+ pflags = WA_EXEC;
break;
default: /* Something weird. Return error. */
return -1;
}
if (after) /* Stop after r/w access is completed. */
- pflags |= AFTER_WATCHFLAG;
+ pflags |= WA_TRAPAFTER;
}
if (!proc_set_watchpoint (pi, addr, len, pflags))
/* Return non-zero if we can set a hardware watchpoint of type TYPE. TYPE
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. */
+ far. */
-static int
-procfs_can_use_hw_breakpoint (struct target_ops *self,
- enum bptype type,
- int cnt, int othertype)
+int
+procfs_target::can_use_hw_breakpoint (enum bptype type, int cnt, int othertype)
{
/* Due to the way that proc_set_watchpoint() is implemented, host
and target pointers must be of the same size. If they are not,
/* Returns non-zero if process is stopped on a hardware watchpoint
fault, else returns zero. */
-static int
-procfs_stopped_by_watchpoint (struct target_ops *ops)
+bool
+procfs_target::stopped_by_watchpoint ()
{
procinfo *pi;
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
- {
- if (proc_why (pi) == PR_FAULTED)
- {
- if (proc_what (pi) == FLTWATCH)
- return 1;
- }
- }
- return 0;
+ if (proc_why (pi) == PR_FAULTED)
+ if (proc_what (pi) == FLTWATCH)
+ return true;
+ return false;
}
/* Returns 1 if the OS knows the position of the triggered watchpoint,
procfs_stopped_by_watchpoint returned 1, thus no further checks are
done. The function also assumes that ADDR is not NULL. */
-static int
-procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr)
+bool
+procfs_target::stopped_data_address (CORE_ADDR *addr)
{
procinfo *pi;
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
return proc_watchpoint_address (pi, addr);
}
-static int
-procfs_insert_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
+int
+procfs_target::insert_watchpoint (CORE_ADDR addr, int len,
+ enum target_hw_bp_type type,
+ struct expression *cond)
{
if (!target_have_steppable_watchpoint
&& !gdbarch_have_nonsteppable_watchpoint (target_gdbarch ()))
- {
- /* 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);
- }
+ /* 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);
else
- {
- /* 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);
- }
+ /* 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);
}
-static int
-procfs_remove_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
+int
+procfs_target::remove_watchpoint (CORE_ADDR addr, int len,
+ enum target_hw_bp_type type,
+ struct expression *cond)
{
return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0);
}
-static int
-procfs_region_ok_for_hw_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len)
+int
+procfs_target::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
return 1;
}
-void
-procfs_use_watchpoints (struct target_ops *t)
-{
- t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
- t->to_insert_watchpoint = procfs_insert_watchpoint;
- t->to_remove_watchpoint = procfs_remove_watchpoint;
- t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint;
- t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
- t->to_stopped_data_address = procfs_stopped_data_address;
-}
-
/* Memory Mappings Functions: */
/* Call a callback function once for each mapping, passing it the
struct prmap *prmaps;
struct prmap *prmap;
int funcstat;
- int map_fd;
int nmap;
- struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
struct stat sbuf;
/* Get the number of mappings, allocate space,
and read the mappings into prmaps. */
/* Open map fd. */
- sprintf (pathname, "/proc/%d/map", pi->pid);
- if ((map_fd = open (pathname, O_RDONLY)) < 0)
- proc_error (pi, "iterate_over_mappings (open)", __LINE__);
+ xsnprintf (pathname, sizeof (pathname), "/proc/%d/map", pi->pid);
- /* Make sure it gets closed again. */
- make_cleanup_close (map_fd);
+ scoped_fd map_fd (open (pathname, O_RDONLY));
+ if (map_fd.get () < 0)
+ proc_error (pi, "iterate_over_mappings (open)", __LINE__);
/* Use stat to determine the file size, and compute
the number of prmap_t objects it contains. */
- if (fstat (map_fd, &sbuf) != 0)
+ if (fstat (map_fd.get (), &sbuf) != 0)
proc_error (pi, "iterate_over_mappings (fstat)", __LINE__);
nmap = sbuf.st_size / sizeof (prmap_t);
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (read (map_fd, (char *) prmaps, nmap * sizeof (*prmaps))
+ if (read (map_fd.get (), (char *) prmaps, nmap * sizeof (*prmaps))
!= (nmap * sizeof (*prmaps)))
proc_error (pi, "iterate_over_mappings (read)", __LINE__);
for (prmap = prmaps; nmap > 0; prmap++, nmap--)
- if ((funcstat = (*func) (prmap, child_func, data)) != 0)
- {
- do_cleanups (cleanups);
- return funcstat;
- }
+ {
+ funcstat = (*func) (prmap, child_func, data);
+ if (funcstat != 0)
+ return funcstat;
+ }
- do_cleanups (cleanups);
return 0;
}
Stops iterating and returns the first non-zero value returned by
the callback. */
-static int
-proc_find_memory_regions (struct target_ops *self,
- find_memory_region_ftype func, void *data)
+int
+procfs_target::find_memory_regions (find_memory_region_ftype func, void *data)
{
- procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
return iterate_over_mappings (pi, func, data,
find_memory_regions_callback);
/* Implement the "info proc" command. */
-static void
-procfs_info_proc (struct target_ops *ops, const char *args,
- enum info_proc_what what)
+bool
+procfs_target::info_proc (const char *args, enum info_proc_what what)
{
- struct cleanup *old_chain;
procinfo *process = NULL;
procinfo *thread = NULL;
char *tmp = NULL;
error (_("Not supported on this target."));
}
- old_chain = make_cleanup (null_cleanup, 0);
gdb_argv built_argv (args);
for (char *arg : built_argv)
{
tid = strtoul (arg + 1, NULL, 10);
}
}
+
+ procinfo_up temporary_procinfo;
if (pid == 0)
- pid = ptid_get_pid (inferior_ptid);
+ pid = inferior_ptid.pid ();
if (pid == 0)
error (_("No current process: you must name one."));
else
/* 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);
+ temporary_procinfo.reset (process);
if (!open_procinfo_files (process, FD_CTL))
proc_error (process, "info proc, open_procinfo_files", __LINE__);
}
}
if (mappings)
- {
- info_proc_mappings (process, 0);
- }
+ info_proc_mappings (process, 0);
- do_cleanups (old_chain);
+ return true;
}
/* Modify the status of the system call identified by SYSCALLNUM in
{
procinfo *pi;
- if (ptid_get_pid (inferior_ptid) <= 0)
+ if (inferior_ptid.pid () <= 0)
error (_("you must be debugging a process to use this command."));
if (args == NULL || args[0] == 0)
error_no_arg (_("system call to trace"));
- pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
if (isdigit (args[0]))
{
const int syscallnum = atoi (args);
proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_RESET);
}
+void _initialize_procfs ();
void
-_initialize_procfs (void)
+_initialize_procfs ()
{
- observer_attach_inferior_created (procfs_inferior_created);
+ gdb::observers::inferior_created.attach (procfs_inferior_created);
add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd,
_("Give a trace of entries into the syscall."));
_("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."));
+
+ add_inf_child_target (&the_procfs_target);
}
/* =================== END, GDB "MODULE" =================== */
ptid_t
procfs_first_available (void)
{
- return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1);
+ return ptid_t (procinfo_list ? procinfo_list->pid : -1);
}
/* =================== GCORE .NOTE "MODULE" =================== */
char *note_data, int *note_size,
enum gdb_signal stop_signal)
{
- struct regcache *regcache = get_thread_regcache (ptid);
+ struct regcache *regcache = get_thread_regcache (&the_procfs_target, ptid);
gdb_gregset_t gregs;
gdb_fpregset_t fpregs;
unsigned long merged_pid;
- merged_pid = ptid_get_lwp (ptid) << 16 | ptid_get_pid (ptid);
+ merged_pid = ptid.lwp () << 16 | ptid.pid ();
/* 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_iterate_over_regset_sections(). */
- scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
- inferior_ptid = ptid;
target_fetch_registers (regcache, -1);
fill_gregset (regcache, &gregs, -1);
if (pi != NULL)
{
- ptid_t ptid = ptid_build (pi->pid, thread->tid, 0);
+ ptid_t ptid = ptid_t (pi->pid, thread->tid, 0);
args->note_data = procfs_do_thread_registers (args->obfd, ptid,
args->note_data,
find_signalled_thread (struct thread_info *info, void *data)
{
if (info->suspend.stop_signal != GDB_SIGNAL_0
- && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
+ && info->ptid.pid () == inferior_ptid.pid ())
return 1;
return 0;
return GDB_SIGNAL_0;
}
-static char *
-procfs_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
+char *
+procfs_target::make_corefile_notes (bfd *obfd, int *note_size)
{
- struct cleanup *old_chain;
gdb_gregset_t gregs;
- gdb_fpregset_t fpregs;
char fname[16] = {'\0'};
char psargs[80] = {'\0'};
- procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
+ procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
char *note_data = NULL;
- char *inf_args;
+ const char *inf_args;
struct procfs_corefile_thread_data thread_args;
- gdb_byte *auxv;
- int auxv_len;
enum gdb_signal stop_signal;
if (get_exec_file (0))
psargs[sizeof (psargs) - 1] = 0;
inf_args = get_inferior_args ();
- if (inf_args && *inf_args &&
- strlen (inf_args) < ((int) sizeof (psargs) - (int) strlen (psargs)))
+ if (inf_args && *inf_args
+ && (strlen (inf_args)
+ < ((int) sizeof (psargs) - (int) strlen (psargs))))
{
strncat (psargs, " ",
sizeof (psargs) - strlen (psargs));
fill_gregset (get_current_regcache (), &gregs, -1);
note_data = elfcore_write_pstatus (obfd, note_data, note_size,
- ptid_get_pid (inferior_ptid),
+ inferior_ptid.pid (),
stop_signal, &gregs);
thread_args.obfd = obfd;
&thread_args);
note_data = thread_args.note_data;
- auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV,
- NULL, &auxv);
- if (auxv_len > 0)
- {
- note_data = elfcore_write_note (obfd, note_data, note_size,
- "CORE", NT_AUXV, auxv, auxv_len);
- xfree (auxv);
- }
+ gdb::optional<gdb::byte_vector> auxv =
+ target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL);
+ if (auxv && !auxv->empty ())
+ note_data = elfcore_write_note (obfd, note_data, note_size,
+ "CORE", NT_AUXV, auxv->data (),
+ auxv->size ());
return note_data;
}