[PATCH 1/3] gdb: remove native support for QNX Neutrino
Simon Marchi
simon.marchi@polymtl.ca
Mon Dec 7 22:33:40 GMT 2020
Remove the native support for the QNX Neutrino OS. This has been
unmaintained for years, and we don't even have a way to see if it builds
or not. Without somebody actively maintaining it, this is just a burden
for developers, having to do changes and guess if they'll even
compile.
This leaves the Neutrino tdep bits in for now, since at least these are
compile-tested. A subsequent patch proposes to remove them too.
gdb/ChangeLog:
* Makefile.in (HFILES_NO_SRCDIR): Remove config/nm-nto.h.
* configure.host: Remove `i[3456]86-*-nto*` support.
* configure.nat: Remove `nto` support.
* config/nm-nto.h: Removed.
* nto-procfs.c: Removed.
gdb/doc/ChangeLog:
* gdb.texinfo (Starting your Program): Remove mention of
Neutrino when debugging locally.
(Native): Remove Neutrino-specific commands.
Change-Id: I4e25ec26ab06636629adebd02ceb161ee31c232d
---
gdb/Makefile.in | 1 -
gdb/config/nm-nto.h | 29 -
gdb/configure.host | 1 -
gdb/configure.nat | 9 -
gdb/doc/gdb.texinfo | 12 +-
gdb/nto-procfs.c | 1610 -------------------------------------------
6 files changed, 1 insertion(+), 1661 deletions(-)
delete mode 100644 gdb/config/nm-nto.h
delete mode 100644 gdb/nto-procfs.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 997c99c30f27..fe6657a6fc3e 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1489,7 +1489,6 @@ HFILES_NO_SRCDIR = \
compile/gcc-c-plugin.h \
compile/gcc-cp-plugin.h \
config/nm-linux.h \
- config/nm-nto.h \
config/djgpp/langinfo.h \
config/djgpp/nl_types.h \
config/i386/nm-i386gnu.h \
diff --git a/gdb/config/nm-nto.h b/gdb/config/nm-nto.h
deleted file mode 100644
index df7403eb3620..000000000000
--- a/gdb/config/nm-nto.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Native support for QNX Neutrino version 6.
-
- Copyright (C) 2003-2020 Free Software Foundation, Inc.
-
- This code was donated by QNX Software Systems Ltd.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef CONFIG_NM_NTO_H
-#define CONFIG_NM_NTO_H
-
-/* Setup the valid realtime signal range. */
-#define REALTIME_LO 41
-#define REALTIME_HI 56
-
-#endif /* CONFIG_NM_NTO_H */
diff --git a/gdb/configure.host b/gdb/configure.host
index ce528237291f..ca4dd9c249e1 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -112,7 +112,6 @@ i[34567]86-*-mingw32*) gdb_host=mingw
i[34567]86-*-msdosdjgpp*) gdb_host=go32 ;;
i[34567]86-*-linux*) gdb_host=linux ;;
i[34567]86-*-gnu*) gdb_host=i386gnu ;;
-i[3456]86-*-nto*) gdb_host=nto ;;
i[34567]86-*-openbsd*) gdb_host=obsd ;;
i[34567]86-*-solaris2* | x86_64-*-solaris2*)
gdb_host=sol2 ;;
diff --git a/gdb/configure.nat b/gdb/configure.nat
index ef2218f0b8d4..93721ba16192 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -404,15 +404,6 @@ case ${gdb_host} in
esac
;;
- nto)
- case ${gdb_host_cpu} in
- i386)
- # Host: Intel 386 running QNX.
- NATDEPFILES='nto-procfs.o'
- NAT_FILE='config/nm-nto.h'
- ;;
- esac
- ;;
obsd)
case ${gdb_host_cpu} in
i386)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 01dcac941c2c..38c2425c55e2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2619,7 +2619,7 @@ environment:
@end smallexample
This command is available when debugging locally on most targets, excluding
-@sc{djgpp}, Cygwin, MS Windows, and QNX Neutrino.
+@sc{djgpp}, Cygwin, MS Windows.
@kindex set startup-with-shell
@anchor{set startup-with-shell}
@@ -23825,16 +23825,6 @@ Show the file to which @code{procfs} API trace is written.
These commands enable and disable tracing of entries into and exits
from the @code{syscall} interface.
-@item info pidlist
-@kindex info pidlist
-@cindex process list, QNX Neutrino
-For QNX Neutrino only, this command displays the list of all the
-processes and all the threads within each process.
-
-@item info meminfo
-@kindex info meminfo
-@cindex mapinfo list, QNX Neutrino
-For QNX Neutrino only, this command displays the list of all mapinfos.
@end table
@node DJGPP Native
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
deleted file mode 100644
index 7831c0b672d7..000000000000
--- a/gdb/nto-procfs.c
+++ /dev/null
@@ -1,1610 +0,0 @@
-/* Machine independent support for QNX Neutrino /proc (process file system)
- for GDB. Written by Colin Burgess at QNX Software Systems Limited.
-
- Copyright (C) 2003-2020 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "defs.h"
-
-#include <fcntl.h>
-#include <spawn.h>
-#include <sys/debug.h>
-#include <sys/procfs.h>
-#include <sys/neutrino.h>
-#include <sys/syspage.h>
-#include <dirent.h>
-#include <sys/netmgr.h>
-#include <sys/auxv.h>
-
-#include "gdbcore.h"
-#include "inferior.h"
-#include "target.h"
-#include "objfiles.h"
-#include "gdbthread.h"
-#include "nto-tdep.h"
-#include "command.h"
-#include "regcache.h"
-#include "solib.h"
-#include "inf-child.h"
-#include "gdbsupport/filestuff.h"
-#include "gdbsupport/scoped_fd.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)
-
-int ctl_fd;
-
-static sighandler_t ofunc;
-
-static procfs_run run;
-
-/* Create the "native" and "procfs" targets. */
-
-struct nto_procfs_target : public inf_child_target
-{
- void open (const char *arg, int from_tty) override;
-
- void attach (const char *, int) override = 0;
-
- void post_attach (int);
-
- void detach (inferior *, int) override;
-
- void resume (ptid_t, int, enum gdb_signal) override;
-
- ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) 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 files_info () override;
-
- int insert_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
- enum remove_bp_reason) override;
-
- int can_use_hw_breakpoint (enum bptype, int, int) override;
-
- int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
-
- int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
-
- bool stopped_by_watchpoint () override;
-
- void kill () override;
-
- void create_inferior (const char *, const std::string &,
- char **, int) override;
-
- void mourn_inferior () override;
-
- void pass_signals (gdb::array_view<const unsigned char>) override;
-
- bool thread_alive (ptid_t ptid) override;
-
- void update_thread_list () override;
-
- std::string pid_to_str (ptid_t) override;
-
- void interrupt () override;
-
- const char *extra_thread_info (struct thread_info *) override;
-
- char *pid_to_exec_file (int pid) override;
-};
-
-/* For "target native". */
-
-static const target_info nto_native_target_info = {
- "native",
- N_("QNX Neutrino local process"),
- N_("QNX Neutrino local process (started by the \"run\" command).")
-};
-
-class nto_procfs_target_native final : public nto_procfs_target
-{
- const target_info &info () const override
- { return nto_native_target_info; }
-};
-
-/* For "target procfs <node>". */
-
-static const target_info nto_procfs_target_info = {
- "procfs",
- N_("QNX Neutrino local or remote process"),
- N_("QNX Neutrino process. target procfs NODE")
-};
-
-struct nto_procfs_target_procfs final : public nto_procfs_target
-{
- const target_info &info () const override
- { return nto_procfs_target_info; }
-};
-
-static ptid_t do_attach (ptid_t ptid);
-
-/* These two globals are only ever set in procfs_open_1, but are
- referenced elsewhere. 'nto_procfs_node' is a flag used to say
- whether we are local, or we should get the current node descriptor
- for the remote QNX node. */
-static char *nodestr;
-static unsigned nto_procfs_node = ND_LOCAL_NODE;
-
-/* Return the current QNX Node, or error out. This is a simple
- wrapper for the netmgr_strtond() function. The reason this
- is required is because QNX node descriptors are transient so
- we have to re-acquire them every time. */
-static unsigned
-nto_node (void)
-{
- unsigned node;
-
- if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0
- || nodestr == NULL)
- return ND_LOCAL_NODE;
-
- node = netmgr_strtond (nodestr, 0);
- if (node == -1)
- error (_("Lost the QNX node. Debug session probably over."));
-
- return (node);
-}
-
-static enum gdb_osabi
-procfs_is_nto_target (bfd *abfd)
-{
- return GDB_OSABI_QNXNTO;
-}
-
-/* This is called when we call 'target native' or 'target procfs
- <arg>' from the (gdb) prompt. For QNX6 (nto), the only valid arg
- will be a QNX node string, eg: "/net/some_node". If arg is not a
- valid QNX node, we will default to local. */
-void
-nto_procfs_target::open (const char *arg, int from_tty)
-{
- char *endstr;
- char buffer[50];
- int total_size;
- procfs_sysinfo *sysinfo;
- char nto_procfs_path[PATH_MAX];
-
- /* Offer to kill previous inferiors before opening this target. */
- target_preopen (from_tty);
-
- nto_is_nto_target = procfs_is_nto_target;
-
- /* Set the default node used for spawning to this one,
- and only override it if there is a valid arg. */
-
- xfree (nodestr);
- nodestr = NULL;
-
- nto_procfs_node = ND_LOCAL_NODE;
- nodestr = (arg != NULL) ? xstrdup (arg) : NULL;
-
- if (nodestr)
- {
- nto_procfs_node = netmgr_strtond (nodestr, &endstr);
- if (nto_procfs_node == -1)
- {
- if (errno == ENOTSUP)
- printf_filtered ("QNX Net Manager not found.\n");
- printf_filtered ("Invalid QNX node %s: error %d (%s).\n", nodestr,
- errno, safe_strerror (errno));
- xfree (nodestr);
- nodestr = NULL;
- nto_procfs_node = ND_LOCAL_NODE;
- }
- else if (*endstr)
- {
- if (*(endstr - 1) == '/')
- *(endstr - 1) = 0;
- else
- *endstr = 0;
- }
- }
- snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s",
- (nodestr != NULL) ? nodestr : "", "/proc");
-
- scoped_fd fd (open (nto_procfs_path, O_RDONLY));
- if (fd.get () == -1)
- {
- printf_filtered ("Error opening %s : %d (%s)\n", nto_procfs_path, errno,
- safe_strerror (errno));
- error (_("Invalid procfs arg"));
- }
-
- sysinfo = (void *) buffer;
- if (devctl (fd.get (), DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
- {
- printf_filtered ("Error getting size: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("Devctl failed."));
- }
- else
- {
- total_size = sysinfo->total_size;
- sysinfo = alloca (total_size);
- if (sysinfo == NULL)
- {
- printf_filtered ("Memory error: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("alloca failed."));
- }
- else
- {
- if (devctl (fd.get (), DCMD_PROC_SYSINFO, sysinfo, total_size, 0)
- != EOK)
- {
- printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("Devctl failed."));
- }
- else
- {
- if (sysinfo->type !=
- nto_map_arch_to_cputype (gdbarch_bfd_arch_info
- (target_gdbarch ())->arch_name))
- error (_("Invalid target CPU."));
- }
- }
- }
-
- inf_child_target::open (arg, from_tty);
- printf_filtered ("Debugging using %s\n", nto_procfs_path);
-}
-
-static void
-procfs_set_thread (ptid_t ptid)
-{
- pid_t tid;
-
- tid = ptid.tid ();
- devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0);
-}
-
-/* Return true if the thread TH is still alive. */
-
-bool
-nto_procfs_target::thread_alive (ptid_t ptid)
-{
- pid_t tid;
- pid_t pid;
- procfs_status status;
- int err;
-
- tid = ptid.tid ();
- pid = ptid.pid ();
-
- if (kill (pid, 0) == -1)
- return false;
-
- status.tid = tid;
- if ((err = devctl (ctl_fd, DCMD_PROC_TIDSTATUS,
- &status, sizeof (status), 0)) != EOK)
- return false;
-
- /* Thread is alive or dead but not yet joined,
- or dead and there is an alive (or dead unjoined) thread with
- higher tid.
-
- If the tid is not the same as requested, requested tid is dead. */
- return (status.tid == tid) && (status.state != STATE_DEAD);
-}
-
-static void
-update_thread_private_data_name (struct thread_info *new_thread,
- const char *newname)
-{
- nto_thread_info *pti = get_nto_thread_info (new_thread);
-
- gdb_assert (newname != NULL);
- gdb_assert (new_thread != NULL);
-
- if (pti)
- {
- pti = new nto_thread_info;
- new_thread->priv.reset (pti);
- }
-
- pti->name = newname;
-}
-
-static void
-update_thread_private_data (struct thread_info *new_thread,
- pthread_t tid, int state, int flags)
-{
- procfs_info pidinfo;
- struct _thread_name *tn;
- procfs_threadctl tctl;
-
-#if _NTO_VERSION > 630
- gdb_assert (new_thread != NULL);
-
- if (devctl (ctl_fd, DCMD_PROC_INFO, &pidinfo,
- sizeof(pidinfo), 0) != EOK)
- return;
-
- memset (&tctl, 0, sizeof (tctl));
- tctl.cmd = _NTO_TCTL_NAME;
- tn = (struct _thread_name *) (&tctl.data);
-
- /* Fetch name for the given thread. */
- tctl.tid = tid;
- tn->name_buf_len = sizeof (tctl.data) - sizeof (*tn);
- tn->new_name_len = -1; /* Getting, not setting. */
- if (devctl (ctl_fd, DCMD_PROC_THREADCTL, &tctl, sizeof (tctl), NULL) != EOK)
- tn->name_buf[0] = '\0';
-
- tn->name_buf[_NTO_THREAD_NAME_MAX] = '\0';
-
- update_thread_private_data_name (new_thread, tn->name_buf);
-
- nto_thread_info *pti = get_nto_thread_info (new_thread);
- pti->tid = tid;
- pti->state = state;
- pti->flags = flags;
-#endif /* _NTO_VERSION */
-}
-
-void
-nto_procfs_target::update_thread_list ()
-{
- procfs_status status;
- pid_t pid;
- ptid_t ptid;
- pthread_t tid;
- struct thread_info *new_thread;
-
- if (ctl_fd == -1)
- return;
-
- prune_threads ();
-
- pid = current_inferior ()->pid;
-
- status.tid = 1;
-
- for (tid = 1;; ++tid)
- {
- if (status.tid == tid
- && (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
- != EOK))
- break;
- if (status.tid != tid)
- /* The reason why this would not be equal is that devctl might have
- returned different tid, meaning the requested tid no longer exists
- (e.g. thread exited). */
- continue;
- ptid = ptid_t (pid, 0, tid);
- new_thread = find_thread_ptid (this, ptid);
- if (!new_thread)
- new_thread = add_thread (ptid);
- update_thread_private_data (new_thread, tid, status.state, 0);
- status.tid++;
- }
- return;
-}
-
-static void
-procfs_pidlist (const char *args, int from_tty)
-{
- struct dirent *dirp = NULL;
- char buf[PATH_MAX];
- procfs_info *pidinfo = NULL;
- procfs_debuginfo *info = NULL;
- procfs_status *status = NULL;
- pid_t num_threads = 0;
- pid_t pid;
- char name[512];
- char procfs_dir[PATH_MAX];
-
- snprintf (procfs_dir, sizeof (procfs_dir), "%s%s",
- (nodestr != NULL) ? nodestr : "", "/proc");
-
- gdb_dir_up dp (opendir (procfs_dir));
- if (dp == NULL)
- {
- fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
- procfs_dir, errno, safe_strerror (errno));
- return;
- }
-
- /* Start scan at first pid. */
- rewinddir (dp.get ());
-
- do
- {
- /* Get the right pid and procfs path for the pid. */
- do
- {
- dirp = readdir (dp.get ());
- if (dirp == NULL)
- return;
- snprintf (buf, sizeof (buf), "%s%s/%s/as",
- (nodestr != NULL) ? nodestr : "",
- "/proc", dirp->d_name);
- pid = atoi (dirp->d_name);
- }
- while (pid == 0);
-
- /* Open the procfs path. */
- scoped_fd fd (open (buf, O_RDONLY));
- if (fd.get () == -1)
- {
- fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n",
- buf, errno, safe_strerror (errno));
- continue;
- }
-
- pidinfo = (procfs_info *) buf;
- if (devctl (fd.get (), DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
- {
- fprintf_unfiltered (gdb_stderr,
- "devctl DCMD_PROC_INFO failed - %d (%s)\n",
- errno, safe_strerror (errno));
- break;
- }
- num_threads = pidinfo->num_threads;
-
- info = (procfs_debuginfo *) buf;
- if (devctl (fd.get (), DCMD_PROC_MAPDEBUG_BASE, info, sizeof (buf), 0)
- != EOK)
- strcpy (name, "unavailable");
- else
- strcpy (name, info->path);
-
- /* Collect state info on all the threads. */
- status = (procfs_status *) buf;
- for (status->tid = 1; status->tid <= num_threads; status->tid++)
- {
- const int err
- = devctl (fd.get (), DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0);
- printf_filtered ("%s - %d", name, pid);
- if (err == EOK && status->tid != 0)
- printf_filtered ("/%d\n", status->tid);
- else
- {
- printf_filtered ("\n");
- break;
- }
- }
- }
- while (dirp != NULL);
-}
-
-static void
-procfs_meminfo (const char *args, int from_tty)
-{
- procfs_mapinfo *mapinfos = NULL;
- static int num_mapinfos = 0;
- procfs_mapinfo *mapinfo_p, *mapinfo_p2;
- int flags = ~0, err, num, i, j;
-
- struct
- {
- procfs_debuginfo info;
- char buff[_POSIX_PATH_MAX];
- } map;
-
- struct info
- {
- unsigned addr;
- unsigned size;
- unsigned flags;
- unsigned debug_vaddr;
- unsigned long long offset;
- };
-
- struct printinfo
- {
- unsigned long long ino;
- unsigned dev;
- struct info text;
- struct info data;
- char name[256];
- } printme;
-
- /* Get the number of map entrys. */
- err = devctl (ctl_fd, DCMD_PROC_MAPINFO, NULL, 0, &num);
- if (err != EOK)
- {
- printf ("failed devctl num mapinfos - %d (%s)\n", err,
- safe_strerror (err));
- return;
- }
-
- mapinfos = XNEWVEC (procfs_mapinfo, num);
-
- num_mapinfos = num;
- mapinfo_p = mapinfos;
-
- /* Fill the map entrys. */
- err = devctl (ctl_fd, DCMD_PROC_MAPINFO, mapinfo_p, num
- * sizeof (procfs_mapinfo), &num);
- if (err != EOK)
- {
- printf ("failed devctl mapinfos - %d (%s)\n", err, safe_strerror (err));
- xfree (mapinfos);
- return;
- }
-
- num = std::min (num, num_mapinfos);
-
- /* Run through the list of mapinfos, and store the data and text info
- so we can print it at the bottom of the loop. */
- for (mapinfo_p = mapinfos, i = 0; i < num; i++, mapinfo_p++)
- {
- if (!(mapinfo_p->flags & flags))
- mapinfo_p->ino = 0;
-
- if (mapinfo_p->ino == 0) /* Already visited. */
- continue;
-
- map.info.vaddr = mapinfo_p->vaddr;
-
- err = devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
- if (err != EOK)
- continue;
-
- memset (&printme, 0, sizeof printme);
- printme.dev = mapinfo_p->dev;
- printme.ino = mapinfo_p->ino;
- printme.text.addr = mapinfo_p->vaddr;
- printme.text.size = mapinfo_p->size;
- printme.text.flags = mapinfo_p->flags;
- printme.text.offset = mapinfo_p->offset;
- printme.text.debug_vaddr = map.info.vaddr;
- strcpy (printme.name, map.info.path);
-
- /* Check for matching data. */
- for (mapinfo_p2 = mapinfos, j = 0; j < num; j++, mapinfo_p2++)
- {
- if (mapinfo_p2->vaddr != mapinfo_p->vaddr
- && mapinfo_p2->ino == mapinfo_p->ino
- && mapinfo_p2->dev == mapinfo_p->dev)
- {
- map.info.vaddr = mapinfo_p2->vaddr;
- err =
- devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
- if (err != EOK)
- continue;
-
- if (strcmp (map.info.path, printme.name))
- continue;
-
- /* Lower debug_vaddr is always text, if necessary, swap. */
- if ((int) map.info.vaddr < (int) printme.text.debug_vaddr)
- {
- memcpy (&(printme.data), &(printme.text),
- sizeof (printme.data));
- printme.text.addr = mapinfo_p2->vaddr;
- printme.text.size = mapinfo_p2->size;
- printme.text.flags = mapinfo_p2->flags;
- printme.text.offset = mapinfo_p2->offset;
- printme.text.debug_vaddr = map.info.vaddr;
- }
- else
- {
- printme.data.addr = mapinfo_p2->vaddr;
- printme.data.size = mapinfo_p2->size;
- printme.data.flags = mapinfo_p2->flags;
- printme.data.offset = mapinfo_p2->offset;
- printme.data.debug_vaddr = map.info.vaddr;
- }
- mapinfo_p2->ino = 0;
- }
- }
- mapinfo_p->ino = 0;
-
- printf_filtered ("%s\n", printme.name);
- printf_filtered ("\ttext=%08x bytes @ 0x%08x\n", printme.text.size,
- printme.text.addr);
- printf_filtered ("\t\tflags=%08x\n", printme.text.flags);
- printf_filtered ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
- printf_filtered ("\t\toffset=%s\n", phex (printme.text.offset, 8));
- if (printme.data.size)
- {
- printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
- printme.data.addr);
- printf_filtered ("\t\tflags=%08x\n", printme.data.flags);
- printf_filtered ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
- printf_filtered ("\t\toffset=%s\n", phex (printme.data.offset, 8));
- }
- printf_filtered ("\tdev=0x%x\n", printme.dev);
- printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
- }
- xfree (mapinfos);
- return;
-}
-
-/* Print status information about what we're accessing. */
-void
-nto_procfs_target::files_info ()
-{
- struct inferior *inf = current_inferior ();
-
- printf_unfiltered ("\tUsing the running image of %s %s via %s.\n",
- inf->attach_flag ? "attached" : "child",
- target_pid_to_str (inferior_ptid).c_str (),
- (nodestr != NULL) ? nodestr : "local node");
-}
-
-/* Target to_pid_to_exec_file implementation. */
-
-char *
-nto_procfs_target::pid_to_exec_file (const int pid)
-{
- int proc_fd;
- static char proc_path[PATH_MAX];
- ssize_t rd;
-
- /* Read exe file name. */
- snprintf (proc_path, sizeof (proc_path), "%s/proc/%d/exefile",
- (nodestr != NULL) ? nodestr : "", pid);
- proc_fd = open (proc_path, O_RDONLY);
- if (proc_fd == -1)
- return NULL;
-
- rd = read (proc_fd, proc_path, sizeof (proc_path) - 1);
- close (proc_fd);
- if (rd <= 0)
- {
- proc_path[0] = '\0';
- return NULL;
- }
- proc_path[rd] = '\0';
- return proc_path;
-}
-
-/* Attach to process PID, then initialize for debugging it. */
-void
-nto_procfs_target::attach (const char *args, int from_tty)
-{
- int pid;
- struct inferior *inf;
-
- pid = parse_pid_to_attach (args);
-
- if (pid == getpid ())
- error (_("Attaching GDB to itself is not a good idea..."));
-
- if (from_tty)
- {
- const char *exec_file = get_exec_file (0);
-
- if (exec_file)
- printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
- target_pid_to_str (ptid_t (pid)).c_str ());
- else
- printf_unfiltered ("Attaching to %s\n",
- target_pid_to_str (ptid_t (pid)).c_str ());
- }
- ptid_t ptid = do_attach (ptid_t (pid));
- inf = current_inferior ();
- inferior_appeared (inf, pid);
- inf->attach_flag = 1;
-
- if (!target_is_pushed (ops))
- push_target (ops);
-
- update_thread_list ();
-
- switch_to_thread (find_thread_ptid (this, ptid));
-}
-
-void
-nto_procfs_target::post_attach (pid_t pid)
-{
- if (current_program_space->exec_bfd ())
- solib_create_inferior_hook (0);
-}
-
-static ptid_t
-do_attach (ptid_t ptid)
-{
- procfs_status status;
- struct sigevent event;
- char path[PATH_MAX];
-
- snprintf (path, PATH_MAX - 1, "%s%s/%d/as",
- (nodestr != NULL) ? nodestr : "", "/proc", ptid.pid ());
- ctl_fd = open (path, O_RDWR);
- if (ctl_fd == -1)
- error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
- safe_strerror (errno));
- if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
- error (_("Couldn't stop process"));
-
- /* Define a sigevent for process stopped notification. */
- event.sigev_notify = SIGEV_SIGNAL_THREAD;
- event.sigev_signo = SIGUSR1;
- event.sigev_code = 0;
- event.sigev_value.sival_ptr = NULL;
- event.sigev_priority = -1;
- devctl (ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
-
- if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
- && status.flags & _DEBUG_FLAG_STOPPED)
- SignalKill (nto_node (), ptid.pid (), 0, SIGCONT, 0, 0);
- nto_init_solib_absolute_prefix ();
- return ptid_t (ptid.pid (), 0, status.tid);
-}
-
-/* Ask the user what to do when an interrupt is received. */
-static void
-interrupt_query (void)
-{
- if (query (_("Interrupted while waiting for the program.\n\
-Give up (and stop debugging it)? ")))
- {
- target_mourn_inferior (inferior_ptid);
- quit ();
- }
-}
-
-/* The user typed ^C twice. */
-static void
-nto_handle_sigint_twice (int signo)
-{
- signal (signo, ofunc);
- interrupt_query ();
- signal (signo, nto_handle_sigint_twice);
-}
-
-static void
-nto_handle_sigint (int signo)
-{
- /* If this doesn't work, try more severe steps. */
- signal (signo, nto_handle_sigint_twice);
-
- target_interrupt ();
-}
-
-sptid_t
-nto_procfs_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
- target_wait_flags options)
-{
- sigset_t set;
- siginfo_t info;
- procfs_status status;
- static int exit_signo = 0; /* To track signals that cause termination. */
-
- ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-
- if (inferior_ptid == null_ptid)
- {
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_0;
- exit_signo = 0;
- return null_ptid;
- }
-
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
-
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- while (!(status.flags & _DEBUG_FLAG_ISTOP))
- {
- ofunc = signal (SIGINT, nto_handle_sigint);
- sigwaitinfo (&set, &info);
- signal (SIGINT, ofunc);
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- }
-
- nto_inferior_data (NULL)->stopped_flags = status.flags;
- nto_inferior_data (NULL)->stopped_pc = status.ip;
-
- if (status.flags & _DEBUG_FLAG_SSTEP)
- {
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_TRAP;
- }
- /* Was it a breakpoint? */
- else if (status.flags & _DEBUG_FLAG_TRACE)
- {
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_TRAP;
- }
- else if (status.flags & _DEBUG_FLAG_ISTOP)
- {
- switch (status.why)
- {
- case _DEBUG_WHY_SIGNALLED:
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig =
- gdb_signal_from_host (status.info.si_signo);
- exit_signo = 0;
- break;
- case _DEBUG_WHY_FAULTED:
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- if (status.info.si_signo == SIGTRAP)
- {
- ourstatus->value.sig = 0;
- exit_signo = 0;
- }
- else
- {
- ourstatus->value.sig =
- gdb_signal_from_host (status.info.si_signo);
- exit_signo = ourstatus->value.sig;
- }
- break;
-
- case _DEBUG_WHY_TERMINATED:
- {
- int waitval = 0;
-
- waitpid (inferior_ptid.pid (), &waitval, WNOHANG);
- if (exit_signo)
- {
- /* Abnormal death. */
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = exit_signo;
- }
- else
- {
- /* Normal death. */
- ourstatus->kind = TARGET_WAITKIND_EXITED;
- ourstatus->value.integer = WEXITSTATUS (waitval);
- }
- exit_signo = 0;
- break;
- }
-
- case _DEBUG_WHY_REQUESTED:
- /* We are assuming a requested stop is due to a SIGINT. */
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_INT;
- exit_signo = 0;
- break;
- }
- }
-
- return ptid_t (status.pid, 0, status.tid);
-}
-
-/* Read the current values of the inferior's registers, both the
- general register set and floating point registers (if supported)
- and update gdb's idea of their current values. */
-void
-nto_procfs_target::fetch_registers (struct regcache *regcache, int regno)
-{
- union
- {
- procfs_greg greg;
- procfs_fpreg fpreg;
- procfs_altreg altreg;
- }
- reg;
- int regsize;
-
- procfs_set_thread (regcache->ptid ());
- if (devctl (ctl_fd, DCMD_PROC_GETGREG, ®, sizeof (reg), ®size) == EOK)
- nto_supply_gregset (regcache, (char *) ®.greg);
- if (devctl (ctl_fd, DCMD_PROC_GETFPREG, ®, sizeof (reg), ®size)
- == EOK)
- nto_supply_fpregset (regcache, (char *) ®.fpreg);
- if (devctl (ctl_fd, DCMD_PROC_GETALTREG, ®, sizeof (reg), ®size)
- == EOK)
- nto_supply_altregset (regcache, (char *) ®.altreg);
-}
-
-/* Helper for procfs_xfer_partial that handles memory transfers.
- Arguments are like target_xfer_partial. */
-
-static enum target_xfer_status
-procfs_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
-{
- int nbytes;
-
- 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. */
-
-enum target_xfer_status
-nto_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)
- {
- case TARGET_OBJECT_MEMORY:
- return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
- case TARGET_OBJECT_AUXV:
- if (readbuf != NULL)
- {
- int err;
- CORE_ADDR initial_stack;
- debug_process_t procinfo;
- /* For 32-bit architecture, size of auxv_t is 8 bytes. */
- const unsigned int sizeof_auxv_t = sizeof (auxv_t);
- const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
- int tempread;
- gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
-
- if (tempbuf == NULL)
- return TARGET_XFER_E_IO;
-
- err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
- sizeof procinfo, 0);
- if (err != EOK)
- return TARGET_XFER_E_IO;
-
- initial_stack = procinfo.initial_stack;
-
- /* procfs is always 'self-hosted', no byte-order manipulation. */
- tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
- sizeof_tempbuf,
- sizeof (auxv_t));
- tempread = std::min (tempread, len) - offset;
- memcpy (readbuf, tempbuf + offset, tempread);
- *xfered_len = tempread;
- return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
- }
- /* Fallthru */
- default:
- return this->beneath ()->xfer_partial (object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
- }
-}
-
-/* Take a program previously attached to and detaches it.
- The program resumes execution and will no longer stop
- on signals, etc. We'd better not have left any breakpoints
- in the program or it'll die when it hits one. */
-void
-nto_procfs_target::detach (inferior *inf, int from_tty)
-{
- target_announce_detach ();
-
- if (siggnal)
- SignalKill (nto_node (), inf->pid, 0, 0, 0, 0);
-
- close (ctl_fd);
- ctl_fd = -1;
-
- switch_to_no_thread ();
- detach_inferior (inf->pid);
- init_thread_list ();
- inf_child_maybe_unpush_target (ops);
-}
-
-static int
-procfs_breakpoint (CORE_ADDR addr, int type, int size)
-{
- procfs_break brk;
-
- brk.type = type;
- brk.addr = addr;
- brk.size = size;
- errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
- if (errno != EOK)
- return 1;
- return 0;
-}
-
-int
-nto_procfs_target::insert_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- bp_tgt->placed_address = bp_tgt->reqstd_address;
- return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
-}
-
-int
-nto_procfs_target::remove_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt,
- enum remove_bp_reason reason)
-{
- return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
-}
-
-int
-nto_procfs_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- bp_tgt->placed_address = bp_tgt->reqstd_address;
- return procfs_breakpoint (bp_tgt->placed_address,
- _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
-}
-
-int
-nto_procfs_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- return procfs_breakpoint (bp_tgt->placed_address,
- _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
-}
-
-void
-nto_procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
-{
- int signal_to_pass;
- procfs_status status;
- sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
-
- if (inferior_ptid == null_ptid)
- return;
-
- procfs_set_thread (ptid == minus_one_ptid ? inferior_ptid :
- ptid);
-
- run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
- if (step)
- run.flags |= _DEBUG_RUN_STEP;
-
- sigemptyset (run_fault);
- sigaddset (run_fault, FLTBPT);
- sigaddset (run_fault, FLTTRACE);
- sigaddset (run_fault, FLTILL);
- sigaddset (run_fault, FLTPRIV);
- sigaddset (run_fault, FLTBOUNDS);
- sigaddset (run_fault, FLTIOVF);
- sigaddset (run_fault, FLTIZDIV);
- sigaddset (run_fault, FLTFPE);
- /* Peter V will be changing this at some point. */
- sigaddset (run_fault, FLTPAGE);
-
- run.flags |= _DEBUG_RUN_ARM;
-
- signal_to_pass = gdb_signal_to_host (signo);
-
- if (signal_to_pass)
- {
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- signal_to_pass = gdb_signal_to_host (signo);
- if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
- {
- if (signal_to_pass != status.info.si_signo)
- {
- SignalKill (nto_node (), inferior_ptid.pid (), 0,
- signal_to_pass, 0, 0);
- run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
- }
- else /* Let it kill the program without telling us. */
- sigdelset (&run.trace, signal_to_pass);
- }
- }
- else
- run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
-
- errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
- if (errno != EOK)
- {
- perror (_("run error!\n"));
- return;
- }
-}
-
-void
-nto_procfs_target::mourn_inferior ()
-{
- if (inferior_ptid != null_ptid)
- {
- SignalKill (nto_node (), inferior_ptid.pid (), 0, SIGKILL, 0, 0);
- close (ctl_fd);
- }
- switch_to_no_thread ();
- init_thread_list ();
- inf_child_mourn_inferior (ops);
-}
-
-/* This function breaks up an argument string into an argument
- vector suitable for passing to execvp().
- E.g., on "run a b c d" this routine would get as input
- the string "a b c d", and as output it would fill in argv with
- the four arguments "a", "b", "c", "d". The only additional
- functionality is simple quoting. The gdb command:
- run a "b c d" f
- will fill in argv with the three args "a", "b c d", "e". */
-static void
-breakup_args (char *scratch, char **argv)
-{
- char *pp, *cp = scratch;
- char quoting = 0;
-
- for (;;)
- {
- /* Scan past leading separators. */
- quoting = 0;
- while (*cp == ' ' || *cp == '\t' || *cp == '\n')
- cp++;
-
- /* Break if at end of string. */
- if (*cp == '\0')
- break;
-
- /* Take an arg. */
- if (*cp == '"')
- {
- cp++;
- quoting = strchr (cp, '"') ? 1 : 0;
- }
-
- *argv++ = cp;
-
- /* Scan for next arg separator. */
- pp = cp;
- if (quoting)
- cp = strchr (pp, '"');
- if ((cp == NULL) || (!quoting))
- cp = strchr (pp, ' ');
- if (cp == NULL)
- cp = strchr (pp, '\t');
- if (cp == NULL)
- cp = strchr (pp, '\n');
-
- /* No separators => end of string => break. */
- if (cp == NULL)
- {
- pp = cp;
- break;
- }
-
- /* Replace the separator with a terminator. */
- *cp++ = '\0';
- }
-
- /* Execv requires a null-terminated arg vector. */
- *argv = NULL;
-}
-
-void
-nto_procfs_target::create_inferior (const char *exec_file,
- const std::string &allargs,
- char **env, int from_tty)
-{
- struct inheritance inherit;
- pid_t pid;
- int flags, errn;
- char **argv, *args;
- const char *in = "", *out = "", *err = "";
- int fd, fds[3];
- sigset_t set;
- struct inferior *inf;
-
- argv = xmalloc ((allargs.size () / (unsigned) 2 + 2) *
- sizeof (*argv));
- argv[0] = const_cast<char *> (get_exec_file (1));
- if (!argv[0])
- {
- if (exec_file)
- argv[0] = exec_file;
- else
- return;
- }
-
- args = xstrdup (allargs.c_str ());
- breakup_args (args, (exec_file != NULL) ? &argv[1] : &argv[0]);
-
- argv = nto_parse_redirection (argv, &in, &out, &err);
-
- fds[0] = STDIN_FILENO;
- fds[1] = STDOUT_FILENO;
- fds[2] = STDERR_FILENO;
-
- /* If the user specified I/O via gdb's --tty= arg, use it, but only
- if the i/o is not also being specified via redirection. */
- const char *inferior_tty = current_inferior ()->tty ();
- if (inferior_tty != nullptr)
- {
- if (!in[0])
- in = inferior_tty;
- if (!out[0])
- out = inferior_tty;
- if (!err[0])
- err = inferior_tty;
- }
-
- if (in[0])
- {
- fd = open (in, O_RDONLY);
- if (fd == -1)
- perror (in);
- else
- fds[0] = fd;
- }
- if (out[0])
- {
- fd = open (out, O_WRONLY);
- if (fd == -1)
- perror (out);
- else
- fds[1] = fd;
- }
- if (err[0])
- {
- fd = open (err, O_WRONLY);
- if (fd == -1)
- perror (err);
- else
- fds[2] = fd;
- }
-
- /* Clear any pending SIGUSR1's but keep the behavior the same. */
- signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
-
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_UNBLOCK, &set, NULL);
-
- memset (&inherit, 0, sizeof (inherit));
-
- if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
- {
- inherit.nd = nto_node ();
- inherit.flags |= SPAWN_SETND;
- inherit.flags &= ~SPAWN_EXEC;
- }
- inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
- inherit.pgroup = SPAWN_NEWPGROUP;
- pid = spawnp (argv[0], 3, fds, &inherit, argv,
- ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
- xfree (args);
-
- sigprocmask (SIG_BLOCK, &set, NULL);
-
- if (pid == -1)
- error (_("Error spawning %s: %d (%s)"), argv[0], errno,
- safe_strerror (errno));
-
- if (fds[0] != STDIN_FILENO)
- close (fds[0]);
- if (fds[1] != STDOUT_FILENO)
- close (fds[1]);
- if (fds[2] != STDERR_FILENO)
- close (fds[2]);
-
- ptid_t ptid = do_attach (ptid_t (pid));
- update_thread_list ();
- switch_to_thread (find_thread_ptid (this, ptid));
-
- inf = current_inferior ();
- inferior_appeared (inf, pid);
- inf->attach_flag = 0;
-
- flags = _DEBUG_FLAG_KLC; /* Kill-on-Last-Close flag. */
- errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
- if (errn != EOK)
- {
- /* FIXME: expected warning? */
- /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
- errn, safe_strerror(errn) ); */
- }
- if (!target_is_pushed (ops))
- push_target (ops);
- target_terminal::init ();
-
- if (current_program_space->exec_bfd () != NULL
- || (current_program_space->symfile_object_file != NULL
- && current_program_space->symfile_object_file->obfd != NULL))
- solib_create_inferior_hook (0);
-}
-
-void
-nto_procfs_target::interrupt ()
-{
- devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
-}
-
-void
-nto_procfs_target::kill ()
-{
- target_mourn_inferior (inferior_ptid);
-}
-
-/* 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
-get_regset (int regset, char *buf, int bufsize, int *regsize)
-{
- int dev_get, dev_set;
- switch (regset)
- {
- case NTO_REG_GENERAL:
- dev_get = DCMD_PROC_GETGREG;
- dev_set = DCMD_PROC_SETGREG;
- break;
-
- case NTO_REG_FLOAT:
- dev_get = DCMD_PROC_GETFPREG;
- dev_set = DCMD_PROC_SETFPREG;
- break;
-
- case NTO_REG_ALT:
- dev_get = DCMD_PROC_GETALTREG;
- dev_set = DCMD_PROC_SETALTREG;
- break;
-
- case NTO_REG_SYSTEM:
- default:
- return -1;
- }
- if (devctl (ctl_fd, dev_get, buf, bufsize, regsize) != EOK)
- return -1;
-
- return dev_set;
-}
-
-void
-nto_procfs_target::store_registers (struct regcache *regcache, int regno)
-{
- union
- {
- procfs_greg greg;
- procfs_fpreg fpreg;
- procfs_altreg altreg;
- }
- reg;
- unsigned off;
- int len, regset, regsize, dev_set, err;
- char *data;
- ptid_t ptid = regcache->ptid ();
-
- if (ptid == null_ptid)
- return;
- procfs_set_thread (ptid);
-
- if (regno == -1)
- {
- for (regset = NTO_REG_GENERAL; regset < NTO_REG_END; regset++)
- {
- dev_set = get_regset (regset, (char *) ®,
- sizeof (reg), ®size);
- if (dev_set == -1)
- continue;
-
- if (nto_regset_fill (regcache, regset, (char *) ®) == -1)
- continue;
-
- err = devctl (ctl_fd, dev_set, ®, regsize, 0);
- if (err != EOK)
- fprintf_unfiltered (gdb_stderr,
- "Warning unable to write regset %d: %s\n",
- regno, safe_strerror (err));
- }
- }
- else
- {
- regset = nto_regset_id (regno);
- if (regset == -1)
- return;
-
- dev_set = get_regset (regset, (char *) ®, sizeof (reg), ®size);
- if (dev_set == -1)
- return;
-
- len = nto_register_area (regcache->arch (),
- regno, regset, &off);
-
- if (len < 1)
- return;
-
- regcache->raw_collect (regno, (char *) ® + off);
-
- err = devctl (ctl_fd, dev_set, ®, regsize, 0);
- if (err != EOK)
- fprintf_unfiltered (gdb_stderr,
- "Warning unable to write regset %d: %s\n", regno,
- safe_strerror (err));
- }
-}
-
-/* Set list of signals to be handled in the target. */
-
-void
-nto_procfs_target::pass_signals
- (gdb::array_view<const unsigned char> pass_signals)
-{
- int signo;
-
- sigfillset (&run.trace);
-
- for (signo = 1; signo < NSIG; signo++)
- {
- int target_signo = gdb_signal_from_host (signo);
- if (target_signo < pass_signals.size () && pass_signals[target_signo])
- sigdelset (&run.trace, signo);
- }
-}
-
-std::string
-nto_procfs_target::pid_to_str (ptid_t ptid)
-{
- int pid, tid;
- struct tidinfo *tip;
-
- pid = ptid.pid ();
- tid = ptid.tid ();
-
-#if 0 /* NYI */
- tip = procfs_thread_info (pid, tid);
- if (tip != NULL)
- snprintf (&buf[n], 1023, " (state = 0x%02x)", tip->state);
-#endif
-
- return string_printf ("process %d", pid);
-}
-
-/* to_can_run implementation for "target procfs". Note this really
- means "can this target be the default run target", which there can
- be only one, and we make it be "target native" like other ports.
- "target procfs <node>" wouldn't make sense as default run target, as
- it needs <node>. */
-
-int
-nto_procfs_target::can_run ()
-{
- return 0;
-}
-
-/* "target procfs". */
-static nto_procfs_target_procfs nto_procfs_ops;
-
-/* "target native". */
-static nto_procfs_target_native nto_native_ops;
-
-/* Create the "native" and "procfs" targets. */
-
-static void
-init_procfs_targets (void)
-{
- /* Register "target native". This is the default run target. */
- add_target (nto_native_target_info, inf_child_open_target);
- set_native_target (&nto_native_ops);
-
- /* Register "target procfs <node>". */
- add_target (nto_procfs_target_info, inf_child_open_target);
-}
-
-#define OSTYPE_NTO 1
-
-void _initialize_procfs ();
-void
-_initialize_procfs ()
-{
- sigset_t set;
-
- init_procfs_targets ();
-
- /* We use SIGUSR1 to gain control after we block waiting for a process.
- We use sigwaitevent to wait. */
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_BLOCK, &set, NULL);
-
- /* Initially, make sure all signals are reported. */
- sigfillset (&run.trace);
-
- /* Stuff some information. */
- nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
- nto_cpuinfo_valid = 1;
-
- add_info ("pidlist", procfs_pidlist, _("pidlist"));
- add_info ("meminfo", procfs_meminfo, _("memory information"));
-
- nto_is_nto_target = procfs_is_nto_target;
-}
-
-
-static int
-procfs_hw_watchpoint (int addr, int len, enum target_hw_bp_type type)
-{
- procfs_break brk;
-
- switch (type)
- {
- case hw_read:
- brk.type = _DEBUG_BREAK_RD;
- break;
- case hw_access:
- brk.type = _DEBUG_BREAK_RW;
- break;
- default: /* Modify. */
-/* FIXME: brk.type = _DEBUG_BREAK_RWM gives EINVAL for some reason. */
- brk.type = _DEBUG_BREAK_RW;
- }
- brk.type |= _DEBUG_BREAK_HW; /* Always ask for HW. */
- brk.addr = addr;
- brk.size = len;
-
- errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
- if (errno != EOK)
- {
- perror (_("Failed to set hardware watchpoint"));
- return -1;
- }
- return 0;
-}
-
-bool
-nto_procfs_target::can_use_hw_breakpoint (enum bptype type,
- int cnt, int othertype)
-{
- return 1;
-}
-
-int
-nto_procfs_target::remove_hw_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
-{
- return procfs_hw_watchpoint (addr, -1, type);
-}
-
-int
-nto_procfs_target::insert_hw_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
-{
- return procfs_hw_watchpoint (addr, len, type);
-}
-
-bool
-nto_procfs_target::stopped_by_watchpoint ()
-{
- /* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are
- stopped due to a SIGTRAP. This assumes gdb works in 'all-stop' mode;
- future gdb versions will likely run in 'non-stop' mode in which case
- we will have to store/examine statuses per thread in question.
- Until then, this will work fine. */
-
- struct inferior *inf = current_inferior ();
- struct nto_inferior_data *inf_data;
-
- gdb_assert (inf != NULL);
-
- inf_data = nto_inferior_data (inf);
-
- return inf_data->stopped_flags
- & (_DEBUG_FLAG_TRACE_RD
- | _DEBUG_FLAG_TRACE_WR
- | _DEBUG_FLAG_TRACE_MODIFY);
-}
--
2.29.2
More information about the Gdb-patches
mailing list