/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#include "gdbthread.h"
#include "regcache.h"
#include "inf-child.h"
+#include "nat/fork-inferior.h"
+#include "filestuff.h"
#if defined (NEW_PROC_API)
#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif
-#include <sys/errno.h>
#include "gdb_wait.h"
#include <signal.h>
#include <ctype.h>
#include "gdb_bfd.h"
-#include <string.h>
#include "inflow.h"
#include "auxv.h"
#include "procfs.h"
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_stop (struct target_ops *self, ptid_t);
+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);
int, unsigned char *);
static void procfs_kill_inferior (struct target_ops *ops);
static void procfs_mourn_inferior (struct target_ops *ops);
-static void procfs_create_inferior (struct target_ops *, char *,
- char *, char **, int);
+static 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 *,
static int procfs_thread_alive (struct target_ops *ops, ptid_t);
-static void procfs_find_new_threads (struct target_ops *ops);
-static char *procfs_pid_to_str (struct target_ops *, ptid_t);
+static void procfs_update_thread_list (struct target_ops *ops);
+static const char *procfs_pid_to_str (struct target_ops *, ptid_t);
static int proc_find_memory_regions (struct target_ops *self,
find_memory_region_ftype, void *);
bfd *, int *);
static int procfs_can_use_hw_breakpoint (struct target_ops *self,
- int, int, int);
+ enum bptype, int, int);
static void procfs_info_proc (struct target_ops *, const char *,
enum info_proc_what);
t->to_xfer_partial = procfs_xfer_partial;
t->to_pass_signals = procfs_pass_signals;
t->to_files_info = procfs_files_info;
- t->to_stop = procfs_stop;
+ t->to_interrupt = procfs_interrupt;
- t->to_find_new_threads = procfs_find_new_threads;
+ 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;
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, char *msg, int killp);
+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 int sysset_t_size (procinfo *p);
#ifdef DYNAMIC_SYSCALLS
static void load_syscalls (procinfo *pi);
static void free_syscalls (procinfo *pi);
-static int find_syscall (procinfo *pi, char *name);
+static int find_syscall (procinfo *pi, const char *name);
#endif /* DYNAMIC_SYSCALLS */
static int iterate_over_mappings
create it if it
doesn't exist yet? */
- pi = (procinfo *) xmalloc (sizeof (procinfo));
+ pi = XNEW (procinfo);
memset (pi, 0, sizeof (procinfo));
pi->pid = pid;
pi->tid = tid;
static void
do_destroy_procinfo_cleanup (void *pi)
{
- destroy_procinfo (pi);
+ destroy_procinfo ((procinfo *) pi);
}
enum { NOKILL, KILL };
destroys the data structure. */
static void
-dead_procinfo (procinfo *pi, char *msg, int kill_p)
+dead_procinfo (procinfo *pi, const char *msg, int kill_p)
{
char procfile[80];
sysset_t *ret;
int size = sysset_t_size (pi);
- ret = xmalloc (size);
+ ret = (sysset_t *) xmalloc (size);
#ifdef DYNAMIC_SYSCALLS
ret->pr_size = ((pi->num_syscalls + (8 * sizeof (uint64_t) - 1))
/ (8 * sizeof (uint64_t)));
maxcall = syscalls[i].pr_number;
pi->num_syscalls = maxcall+1;
- pi->syscall_names = xmalloc (pi->num_syscalls * sizeof (char *));
+ pi->syscall_names = XNEWVEC (char *, pi->num_syscalls);
for (i = 0; i < pi->num_syscalls; i++)
pi->syscall_names[i] = NULL;
If no match is found, return -1. */
static int
-find_syscall (procinfo *pi, char *name)
+find_syscall (procinfo *pi, const char *name)
{
int i;
void *ptr);
static void
-proc_warn (procinfo *pi, char *func, int line)
+proc_warn (procinfo *pi, const char *func, int line)
{
sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
print_sys_errmsg (errmsg, errno);
}
static void
-proc_error (procinfo *pi, char *func, int line)
+proc_error (procinfo *pi, const char *func, int line)
{
sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
perror_with_name (errmsg);
- sizeof (sysset_t)
+ sysset_t_size (pi);
- argp = xmalloc (argp_size);
+ argp = (struct gdb_proc_ctl_pcsentry *) xmalloc (argp_size);
argp->cmd = PCSENTRY;
memcpy (&argp->sysset, sysset, sysset_t_size (pi));
- sizeof (sysset_t)
+ sysset_t_size (pi);
- argp = xmalloc (argp_size);
+ argp = (struct gdb_proc_ctl_pcsexit *) xmalloc (argp_size);
argp->cmd = PCSEXIT;
memcpy (&argp->sysset, sysset, sysset_t_size (pi));
/* Allocate space for one LDT entry.
This alloc must persist, because we return a pointer to it. */
if (ldt_entry == NULL)
- ldt_entry = (struct ssd *) xmalloc (sizeof (struct ssd));
+ ldt_entry = XNEW (struct ssd);
/* Open the file descriptor for the LDT table. */
sprintf (pathname, "/proc/%d/ldt", pi->pid);
break; /* end of table */
/* If key matches, return this entry. */
if (ldt_entry->sel == key)
- return ldt_entry;
+ {
+ do_cleanups (old_chain);
+ return ldt_entry;
+ }
}
/* Loop ended, match not found. */
+ do_cleanups (old_chain);
return NULL;
#else
int nldt, i;
if ((nlwp = proc_get_nthreads (pi)) <= 1)
return 1; /* Process is not multi-threaded; nothing to do. */
- prstatus = xmalloc (sizeof (gdb_prstatus_t) * (nlwp + 1));
+ prstatus = XNEWVEC (gdb_prstatus_t, nlwp + 1);
old_chain = make_cleanup (xfree, prstatus);
if (ioctl (pi->ctl_fd, PIOCLSTATUS, prstatus) < 0)
static void
do_closedir_cleanup (void *dir)
{
- closedir (dir);
+ closedir ((DIR *) dir);
}
static int
if (nthreads < 2)
return 0; /* Nothing to do for 1 or fewer threads. */
- threads = xmalloc (nthreads * sizeof (tid_t));
+ threads = XNEWVEC (tid_t, nthreads);
if (ioctl (pi->ctl_fd, PIOCTLIST, threads) < 0)
proc_error (pi, "procfs: update_threads (PIOCTLIST)", __LINE__);
static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
int entry_or_exit, int mode, int from_tty);
-/* On mips-irix, we need to insert a breakpoint at __dbx_link during
- the startup phase. The following two variables are used to record
- the address of the breakpoint, and the code that was replaced by
- a breakpoint. */
-static int dbx_link_bpt_addr = 0;
-static void *dbx_link_bpt;
-
/* Sets up the inferior to be debugged. Registers to trace signals,
hardware faults, and syscalls. Note: does not set RLC flag: caller
may want to customize that. Returns zero for success (note!
sysset_t *traced_syscall_exits;
int status;
-#ifdef PROCFS_DONT_TRACE_FAULTS
- /* On some systems (OSF), we don't trace hardware faults.
- Apparently it's enough that we catch them as signals.
- Wonder why we don't just do that in general? */
- premptyset (&traced_faults); /* don't trace faults. */
-#else
/* Register to trace hardware faults in the child. */
prfillset (&traced_faults); /* trace all faults... */
gdb_prdelset (&traced_faults, FLTPAGE); /* except page fault. */
-#endif
if (!proc_set_traced_faults (pi, &traced_faults))
return __LINE__;
if (from_tty)
{
- char *exec_file;
+ const char *exec_file;
exec_file = get_exec_file (0);
if (exec_file == NULL)
{
gdb_gregset_t *gregs;
procinfo *pi;
- int pid = ptid_get_pid (inferior_ptid);
- int tid = ptid_get_lwp (inferior_ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ ptid_t ptid = regcache_get_ptid (regcache);
+ int pid = ptid_get_pid (ptid);
+ int tid = ptid_get_lwp (ptid);
+ 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 (inferior_ptid));
+ target_pid_to_str (ptid));
gregs = proc_get_gregs (pi);
if (gregs == NULL)
{
gdb_gregset_t *gregs;
procinfo *pi;
- int pid = ptid_get_pid (inferior_ptid);
- int tid = ptid_get_lwp (inferior_ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ ptid_t ptid = regcache_get_ptid (regcache);
+ int pid = ptid_get_pid (ptid);
+ int tid = ptid_get_lwp (ptid);
+ 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 (inferior_ptid));
+ target_pid_to_str (ptid));
gregs = proc_get_gregs (pi);
if (gregs == NULL)
return 0;
}
-/* 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;
-}
-
#ifdef SYS_syssgi
/* Return the address of the __dbx_link() function in the file
refernced by ABFD by scanning its symbol table. Return 0 if
static int
insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
{
- bfd *abfd;
long storage_needed;
CORE_ADDR sym_addr;
- abfd = gdb_bfd_fdopenr ("unamed", 0, fd);
+ gdb_bfd_ref_ptr abfd (gdb_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))
+ if (!bfd_check_format (abfd.get (), bfd_object))
{
/* Not the correct format, so we can not possibly find the dbx_link
symbol in it. */
- gdb_bfd_unref (abfd);
return 0;
}
- sym_addr = dbx_link_addr (abfd);
+ sym_addr = dbx_link_addr (abfd.get ());
if (sym_addr != 0)
{
+ struct breakpoint *dbx_link_bpt;
+
/* Insert the breakpoint. */
- dbx_link_bpt_addr = sym_addr;
- dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
- sym_addr);
+ dbx_link_bpt
+ = create_and_insert_solib_event_breakpoint (target_gdbarch (),
+ sym_addr);
if (dbx_link_bpt == NULL)
{
warning (_("Failed to insert dbx_link breakpoint."));
- gdb_bfd_unref (abfd);
return 0;
}
- gdb_bfd_unref (abfd);
return 1;
}
- gdb_bfd_unref (abfd);
return 0;
}
else
{
/* How to keep going without returning to wfi: */
- target_resume (ptid, 0, GDB_SIGNAL_0);
+ target_continue_no_signal (ptid);
goto wait_again;
}
}
/* 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, GDB_SIGNAL_0);
+ target_continue_no_signal (ptid);
goto wait_again;
}
#endif
add_thread (temp_ptid);
status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = 0;
+ status->value.sig = GDB_SIGNAL_0;
return retval;
}
#endif
#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:
kill(SIGINT) to the child's process group. */
static void
-procfs_stop (struct target_ops *self, ptid_t ptid)
+procfs_interrupt (struct target_ops *self, ptid_t ptid)
{
kill (-inferior_process_group (), SIGINT);
}
int parent_pid;
parent_pid = proc_parent_pid (pi);
-#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
- /* FIXME: use access functions. */
- /* Alpha OSF/1-3.x procfs needs a clear of the current signal
- before the PIOCKILL, otherwise it might generate a corrupted core
- file for the inferior. */
- if (ioctl (pi->ctl_fd, PIOCSSIG, NULL) < 0)
- {
- printf_filtered ("unconditionally_kill: SSIG failed!\n");
- }
-#endif
#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
/* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
to kill the inferior, otherwise it might remain stopped with a
if (pi)
unconditionally_kill_inferior (pi);
- target_mourn_inferior ();
+ target_mourn_inferior (inferior_ptid);
}
}
generic_mourn_inferior ();
- if (dbx_link_bpt != NULL)
- {
- deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt);
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
- }
-
inf_child_maybe_unpush_target (ops);
}
thread_change_ptid (pid_to_ptid (pid),
ptid_build (pid, lwpid, 0));
- startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+ gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
#ifdef SYS_syssgi
/* On mips-irix, we need to stop the inferior early enough during
inf-ptrace? */
static void
-procfs_create_inferior (struct target_ops *ops, char *exec_file,
- char *allargs, char **env, int from_tty)
+procfs_create_inferior (struct target_ops *ops, const char *exec_file,
+ const std::string &allargs, char **env, int from_tty)
{
char *shell_file = getenv ("SHELL");
char *tryname;
if the caller is the superuser; failing to use it loses if
there are ACLs or some such. */
- char *p;
- char *p1;
+ const char *p;
+ const char *p1;
/* FIXME-maybe: might want "set path" command so user can change what
path is used from within GDB. */
- char *path = getenv ("PATH");
+ const char *path = getenv ("PATH");
int len;
struct stat statbuf;
if (path == NULL)
path = "/bin:/usr/bin";
- tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+ tryname = (char *) alloca (strlen (path) + strlen (shell_file) + 2);
for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
{
p1 = strchr (p, ':');
pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
NULL, NULL, 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));
+
procfs_init_inferior (ops, pid);
}
#endif
}
-/* Callback for find_new_threads. Calls "add_thread". */
+/* Callback for update_thread_list. Calls "add_thread". */
static int
procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
back to GDB to add to its list. */
static void
-procfs_find_new_threads (struct target_ops *ops)
+procfs_update_thread_list (struct target_ops *ops)
{
procinfo *pi;
+ prune_threads ();
+
/* Find procinfo for main process. */
pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
proc_update_threads (pi);
/* Convert PTID to a string. Returns the string in a static
buffer. */
-static char *
+static const char *
procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
static char buf[80];
static int
procfs_can_use_hw_breakpoint (struct target_ops *self,
- int type, int cnt, int othertype)
+ 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,
static int
procfs_insert_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len, int type,
+ CORE_ADDR addr, int len,
+ enum target_hw_bp_type type,
struct expression *cond)
{
if (!target_have_steppable_watchpoint
static int
procfs_remove_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len, int type,
+ CORE_ADDR addr, int len,
+ enum target_hw_bp_type type,
struct expression *cond)
{
return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0);
struct cleanup *old_chain;
procinfo *process = NULL;
procinfo *thread = NULL;
- char **argv = NULL;
char *tmp = NULL;
int pid = 0;
int tid = 0;
}
old_chain = make_cleanup (null_cleanup, 0);
- if (args)
+ gdb_argv built_argv (args);
+ for (char *arg : built_argv)
{
- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
- }
- while (argv != NULL && *argv != NULL)
- {
- if (isdigit (argv[0][0]))
+ if (isdigit (arg[0]))
{
- pid = strtoul (argv[0], &tmp, 10);
+ pid = strtoul (arg, &tmp, 10);
if (*tmp == '/')
tid = strtoul (++tmp, NULL, 10);
}
- else if (argv[0][0] == '/')
+ else if (arg[0] == '/')
{
- tid = strtoul (argv[0] + 1, NULL, 10);
+ tid = strtoul (arg + 1, NULL, 10);
}
- argv++;
}
if (pid == 0)
pid = ptid_get_pid (inferior_ptid);
proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_RESET);
}
-
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern void _initialize_procfs (void);
-
void
_initialize_procfs (void)
{
gdb_gregset_t gregs;
gdb_fpregset_t fpregs;
unsigned long merged_pid;
- struct cleanup *old_chain;
merged_pid = ptid_get_lwp (ptid) << 16 | ptid_get_pid (ptid);
/* 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(). */
+ gdbarch_iterate_over_regset_sections(). */
- old_chain = save_inferior_ptid ();
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ptid;
target_fetch_registers (regcache, -1);
&fpregs,
sizeof (fpregs));
- do_cleanups (old_chain);
-
return note_data;
}
static int
procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data)
{
- struct procfs_corefile_thread_data *args = data;
+ struct procfs_corefile_thread_data *args
+ = (struct procfs_corefile_thread_data *) data;
if (pi != NULL)
{