/* Machine independent support for QNX Neutrino /proc (process file system)
for GDB. Written by Colin Burgess at QNX Software Systems Limited.
- Copyright (C) 2003, 2006-2012 Free Software Foundation, Inc.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
Contributed by QNX Software Systems Ltd.
#include <sys/procfs.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
-#include "gdb_dirent.h"
+#include <dirent.h>
#include <sys/netmgr.h>
#include "exceptions.h"
-#include "gdb_string.h"
+#include <string.h>
#include "gdbcore.h"
#include "inferior.h"
#include "target.h"
#include "command.h"
#include "regcache.h"
#include "solib.h"
+#include "inf-child.h"
#define NULL_PID 0
#define _DEBUG_FLAG_TRACE (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
_DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
-static struct target_ops procfs_ops;
-
int ctl_fd;
static void (*ofunc) ();
static void procfs_open (char *, int);
-static int procfs_can_run (void);
-
-static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, int, int,
- struct mem_attrib *attrib,
- struct target_ops *);
-
-static void init_procfs_ops (void);
-
static ptid_t do_attach (ptid_t ptid);
-static int procfs_can_use_hw_breakpoint (int, int, int);
+static int procfs_can_use_hw_breakpoint (struct target_ops *self,
+ int, int, int);
-static int procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type,
+static int procfs_insert_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond);
-static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type,
+static int procfs_remove_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond);
-static int procfs_stopped_by_watchpoint (void);
+static int procfs_stopped_by_watchpoint (struct target_ops *ops);
/* These two globals are only ever set in procfs_open(), but are
referenced elsewhere. 'nto_procfs_node' is a flag used to say
{
if (sysinfo->type !=
nto_map_arch_to_cputype (gdbarch_bfd_arch_info
- (target_gdbarch)->arch_name))
+ (target_gdbarch ())->arch_name))
error (_("Invalid target CPU."));
}
}
target_pid_to_str (inferior_ptid), nto_procfs_path);
}
-/* Mark our target-struct as eligible for stray "run" and "attach"
- commands. */
-static int
-procfs_can_run (void)
-{
- return 1;
-}
-
/* Attach to process PID, then initialize for debugging it. */
static void
procfs_attach (struct target_ops *ops, char *args, int from_tty)
}
static void
-procfs_post_attach (pid_t pid)
+procfs_post_attach (struct target_ops *self, pid_t pid)
{
if (exec_bfd)
solib_create_inferior_hook (0);
struct sigevent event;
char path[PATH_MAX];
- snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path, PIDGET (ptid));
+ snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path,
+ ptid_get_pid (ptid));
ctl_fd = open (path, O_RDWR);
if (ctl_fd == -1)
error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
&& status.flags & _DEBUG_FLAG_STOPPED)
- SignalKill (nto_node (), PIDGET (ptid), 0, SIGCONT, 0, 0);
+ SignalKill (nto_node (), ptid_get_pid (ptid), 0, SIGCONT, 0, 0);
nto_init_solib_absolute_prefix ();
- return ptid_build (PIDGET (ptid), 0, status.tid);
+ return ptid_build (ptid_get_pid (ptid), 0, status.tid);
}
/* Ask the user what to do when an interrupt is received. */
Give up (and stop debugging it)? ")))
{
target_mourn_inferior ();
- deprecated_throw_reason (RETURN_QUIT);
+ quit ();
}
target_terminal_inferior ();
{
int waitval = 0;
- waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
+ waitpid (ptid_get_pid (inferior_ptid), &waitval, WNOHANG);
if (exit_signo)
{
/* Abnormal death. */
nto_supply_altregset (regcache, (char *) ®.altreg);
}
-/* Copy LEN bytes to/from inferior's memory starting at MEMADDR
- from/to debugger memory starting at MYADDR. Copy from inferior
- if DOWRITE is zero or to inferior if DOWRITE is nonzero.
+/* Helper for procfs_xfer_partial that handles memory transfers.
+ Arguments are like target_xfer_partial. */
- Returns the length copied, which is either the LEN argument or
- zero. This xfer function does not do partial moves, since procfs_ops
- doesn't allow memory operations to cross below us in the target stack
- anyway. */
-static int
-procfs_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int dowrite,
- struct mem_attrib *attrib, struct target_ops *target)
+static enum target_xfer_status
+procfs_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
- int nbytes = 0;
+ int nbytes;
- if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
+ if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) != (off_t) memaddr)
+ return TARGET_XFER_E_IO;
+
+ if (writebuf != NULL)
+ nbytes = write (ctl_fd, writebuf, len);
+ else
+ nbytes = read (ctl_fd, readbuf, len);
+ if (nbytes <= 0)
+ return TARGET_XFER_E_IO;
+ *xfered_len = nbytes;
+ return TARGET_XFER_OK;
+}
+
+/* Target to_xfer_partial implementation. */
+
+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)
+{
+ switch (object)
{
- if (dowrite)
- nbytes = write (ctl_fd, myaddr, len);
- else
- nbytes = read (ctl_fd, myaddr, len);
- if (nbytes < 0)
- nbytes = 0;
+ case TARGET_OBJECT_MEMORY:
+ return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
+ default:
+ return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+ readbuf, writebuf, offset, len);
}
- return (nbytes);
}
/* Take a program previously attached to and detaches it.
on signals, etc. We'd better not have left any breakpoints
in the program or it'll die when it hits one. */
static void
-procfs_detach (struct target_ops *ops, char *args, int from_tty)
+procfs_detach (struct target_ops *ops, const char *args, int from_tty)
{
int siggnal = 0;
int pid;
siggnal = atoi (args);
if (siggnal)
- SignalKill (nto_node (), PIDGET (inferior_ptid), 0, siggnal, 0, 0);
+ SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0, siggnal, 0, 0);
close (ctl_fd);
ctl_fd = -1;
inferior_ptid = null_ptid;
detach_inferior (pid);
init_thread_list ();
- unpush_target (&procfs_ops); /* Pop out of handling an inferior. */
+ unpush_target (ops); /* Pop out of handling an inferior. */
}
static int
}
static int
-procfs_insert_breakpoint (struct gdbarch *gdbarch,
+procfs_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
}
static int
-procfs_remove_breakpoint (struct gdbarch *gdbarch,
+procfs_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
}
static int
-procfs_insert_hw_breakpoint (struct gdbarch *gdbarch,
+procfs_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address,
}
static int
-procfs_remove_hw_breakpoint (struct gdbarch *gdbarch,
+procfs_remove_hw_breakpoint (struct target_ops *self,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address,
{
if (signal_to_pass != status.info.si_signo)
{
- SignalKill (nto_node (), PIDGET (inferior_ptid), 0,
+ SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0,
signal_to_pass, 0, 0);
run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
}
{
if (!ptid_equal (inferior_ptid, null_ptid))
{
- SignalKill (nto_node (), PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
+ SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0, SIGKILL, 0, 0);
close (ctl_fd);
}
inferior_ptid = null_ptid;
init_thread_list ();
- unpush_target (&procfs_ops);
+ unpush_target (ops);
generic_mourn_inferior ();
}
}
static void
-procfs_stop (ptid_t ptid)
+procfs_stop (struct target_ops *self, ptid_t ptid)
{
devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
}
target_mourn_inferior ();
}
-/* Store register REGNO, or all registers if REGNO == -1, from the contents
- of REGISTERS. */
-static void
-procfs_prepare_to_store (struct regcache *regcache)
-{
-}
-
/* Fill buf with regset and return devctl cmd to do the setting. Return
-1 if we fail to get the regset. Store size of regset in regsize. */
static int
/* Set list of signals to be handled in the target. */
static void
-procfs_pass_signals (int numsigs, unsigned char *pass_signals)
+procfs_pass_signals (struct target_ops *self,
+ int numsigs, unsigned char *pass_signals)
{
int signo;
return buf;
}
-static void
-init_procfs_ops (void)
+/* Create a nto-procfs target. */
+
+static struct target_ops *
+procfs_target (void)
{
- procfs_ops.to_shortname = "procfs";
- procfs_ops.to_longname = "QNX Neutrino procfs child process";
- procfs_ops.to_doc =
- "QNX Neutrino procfs child process (started by the \"run\" command).\n\
+ struct target_ops *t = inf_child_target ();
+
+ t->to_shortname = "procfs";
+ t->to_longname = "QNX Neutrino procfs child process";
+ t->to_doc
+ = "QNX Neutrino procfs child process (started by the \"run\" command).\n\
target procfs <node>";
- procfs_ops.to_open = procfs_open;
- procfs_ops.to_attach = procfs_attach;
- procfs_ops.to_post_attach = procfs_post_attach;
- procfs_ops.to_detach = procfs_detach;
- procfs_ops.to_resume = procfs_resume;
- procfs_ops.to_wait = procfs_wait;
- procfs_ops.to_fetch_registers = procfs_fetch_registers;
- procfs_ops.to_store_registers = procfs_store_registers;
- procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
- procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
- procfs_ops.to_files_info = procfs_files_info;
- procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
- procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
- procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
- procfs_ops.to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
- procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
- procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
- procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
- procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
- 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_info = child_terminal_info;
- procfs_ops.to_kill = procfs_kill_inferior;
- procfs_ops.to_create_inferior = procfs_create_inferior;
- procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
- procfs_ops.to_can_run = procfs_can_run;
- procfs_ops.to_pass_signals = procfs_pass_signals;
- procfs_ops.to_thread_alive = procfs_thread_alive;
- procfs_ops.to_find_new_threads = procfs_find_new_threads;
- procfs_ops.to_pid_to_str = procfs_pid_to_str;
- procfs_ops.to_stop = procfs_stop;
- procfs_ops.to_stratum = process_stratum;
- procfs_ops.to_has_all_memory = default_child_has_all_memory;
- procfs_ops.to_has_memory = default_child_has_memory;
- procfs_ops.to_has_stack = default_child_has_stack;
- procfs_ops.to_has_registers = default_child_has_registers;
- procfs_ops.to_has_execution = default_child_has_execution;
- procfs_ops.to_magic = OPS_MAGIC;
- procfs_ops.to_have_continuable_watchpoint = 1;
- procfs_ops.to_extra_thread_info = nto_extra_thread_info;
+ t->to_open = procfs_open;
+ t->to_attach = procfs_attach;
+ t->to_post_attach = procfs_post_attach;
+ t->to_detach = procfs_detach;
+ t->to_resume = procfs_resume;
+ t->to_wait = procfs_wait;
+ t->to_fetch_registers = procfs_fetch_registers;
+ t->to_store_registers = procfs_store_registers;
+ t->to_xfer_partial = procfs_xfer_partial;
+ t->to_files_info = procfs_files_info;
+ t->to_insert_breakpoint = procfs_insert_breakpoint;
+ t->to_remove_breakpoint = procfs_remove_breakpoint;
+ t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+ t->to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
+ t->to_remove_hw_breakpoint = procfs_remove_hw_breakpoint;
+ t->to_insert_watchpoint = procfs_insert_hw_watchpoint;
+ t->to_remove_watchpoint = procfs_remove_hw_watchpoint;
+ t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+ t->to_kill = procfs_kill_inferior;
+ t->to_create_inferior = procfs_create_inferior;
+ t->to_mourn_inferior = procfs_mourn_inferior;
+ t->to_pass_signals = procfs_pass_signals;
+ t->to_thread_alive = procfs_thread_alive;
+ t->to_find_new_threads = procfs_find_new_threads;
+ t->to_pid_to_str = procfs_pid_to_str;
+ t->to_stop = procfs_stop;
+ t->to_have_continuable_watchpoint = 1;
+ t->to_extra_thread_info = nto_extra_thread_info;
+
+ return t;
}
#define OSTYPE_NTO 1
_initialize_procfs (void)
{
sigset_t set;
+ struct target_ops *t;
- init_procfs_ops ();
- add_target (&procfs_ops);
+ t = procfs_target ();
+ add_target (t);
/* We use SIGUSR1 to gain control after we block waiting for a process.
We use sigwaitevent to wait. */
}
static int
-procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
+procfs_can_use_hw_breakpoint (struct target_ops *self,
+ int type, int cnt, int othertype)
{
return 1;
}
static int
-procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type,
+procfs_remove_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond)
{
return procfs_hw_watchpoint (addr, -1, type);
}
static int
-procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type,
+procfs_insert_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond)
{
return procfs_hw_watchpoint (addr, len, type);
}
static int
-procfs_stopped_by_watchpoint (void)
+procfs_stopped_by_watchpoint (struct target_ops *ops)
{
return 0;
}