pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

gdb-server: Update gdbserver patches



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Wed Sep 2 18:09:58 2020 +0200
Changeset:	92fd532fe2f8dd2fad539ddbc7676077e14b594a

Modified Files:
	gdb-netbsd/distinfo
	gdb-netbsd/patches/patch-gdbserver_configure.srv
	gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc
	gdb-netbsd/patches/patch-gdbserver_netbsd-low.h
	gdb-netbsd/patches/patch-gdbserver_netbsd-x86__64-low.cc
Added Files:
	gdb-netbsd/patches/patch-gdb_configure.nat
	gdb-netbsd/patches/patch-gdb_nat_fork-inferior.c
	gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.c
	gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.h
	gdb-netbsd/patches/patch-gdb_nbsd-nat.c
	gdb-netbsd/patches/patch-gdbsupport_eintr.h

Log Message:
gdb-server: Update gdbserver patches

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=92fd532fe2f8dd2fad539ddbc7676077e14b594a

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 gdb-netbsd/distinfo                                |   14 +-
 gdb-netbsd/patches/patch-gdb_configure.nat         |   13 +
 gdb-netbsd/patches/patch-gdb_nat_fork-inferior.c   |   16 +
 gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.c      |  216 ++++
 gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.h      |   52 +
 gdb-netbsd/patches/patch-gdb_nbsd-nat.c            |  236 ++++
 gdb-netbsd/patches/patch-gdbserver_configure.srv   |    3 +-
 gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc   | 1298 ++++++++------------
 gdb-netbsd/patches/patch-gdbserver_netbsd-low.h    |   14 +-
 .../patches/patch-gdbserver_netbsd-x86__64-low.cc  |    2 +-
 gdb-netbsd/patches/patch-gdbsupport_eintr.h        |   46 +
 11 files changed, 1127 insertions(+), 783 deletions(-)

diffs:
diff --git a/gdb-netbsd/distinfo b/gdb-netbsd/distinfo
index a69acdb30b..8c4270b59c 100644
--- a/gdb-netbsd/distinfo
+++ b/gdb-netbsd/distinfo
@@ -4,8 +4,14 @@ SHA1 (gdb-8.2.1-05fd99cc80b1955e8c846dacfa57fe52816d4869.tar.gz) = 8e5ba0ea9f513
 RMD160 (gdb-8.2.1-05fd99cc80b1955e8c846dacfa57fe52816d4869.tar.gz) = 90987ca409c82bc96c5f3aad04b2d38afce8e5a4
 SHA512 (gdb-8.2.1-05fd99cc80b1955e8c846dacfa57fe52816d4869.tar.gz) = eaa4eaa9a8db968f216077cad4b730b2d6d273cf5205075bcef102c9ca21e85ed2b22e85d5be6bda7c3c4069290f6b7294550e5e6095dcd4401c8d70998162c1
 Size (gdb-8.2.1-05fd99cc80b1955e8c846dacfa57fe52816d4869.tar.gz) = 60902858 bytes
+SHA1 (patch-gdb_configure.nat) = 7806b08e423fca823f3b525c0018fa9fe9aaa41c
+SHA1 (patch-gdb_nat_fork-inferior.c) = 3d800887af4fa8ce3d18f7b4416cba2fa8b6f487
+SHA1 (patch-gdb_nat_netbsd-nat.c) = 42048f8f0184d4aa8c7fbbfb4e5656151be39707
+SHA1 (patch-gdb_nat_netbsd-nat.h) = c2def3bb32c67fd02c7e9ea242c7ccceee26d18c
+SHA1 (patch-gdb_nbsd-nat.c) = 6313f30db292b466e2f2dd00f975bf3e45f0d0c5
 SHA1 (patch-gdbserver_Makefile.in) = 94d6abcf997fdc3cbf9c9ddab34cb242b7f54c76
-SHA1 (patch-gdbserver_configure.srv) = 5a70d03065f58a90c7ef12e293e0c65c0a4f869a
-SHA1 (patch-gdbserver_netbsd-low.cc) = 5afebe61bf8b9c8b3c2bf055e9f59e15bc76bc81
-SHA1 (patch-gdbserver_netbsd-low.h) = 1a636f92c703f9e3049fa97f177f1d808c62a6ed
-SHA1 (patch-gdbserver_netbsd-x86__64-low.cc) = 9f9d9da379cb11054068325375b4e6005e622101
+SHA1 (patch-gdbserver_configure.srv) = 14937ff7334c5efc013ba30cc6d1116c034e0618
+SHA1 (patch-gdbserver_netbsd-low.cc) = 13cb703fda319fc50f3927cd51a464659cc10b1b
+SHA1 (patch-gdbserver_netbsd-low.h) = 6bae8bf34714db16c667387f12aafaaad8c1f0dd
+SHA1 (patch-gdbserver_netbsd-x86__64-low.cc) = 860e3bb6ce5ca28ca2bab98ed6b975886847759e
+SHA1 (patch-gdbsupport_eintr.h) = 57ee80d3335f49636fd570459fbe72fa434f93ba
diff --git a/gdb-netbsd/patches/patch-gdb_configure.nat b/gdb-netbsd/patches/patch-gdb_configure.nat
new file mode 100644
index 0000000000..25888b0a95
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdb_configure.nat
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- gdb/configure.nat.orig	2020-08-26 18:57:35.000000000 +0000
++++ gdb/configure.nat
+@@ -68,7 +68,7 @@ case ${gdb_host} in
+ 	LOADLIBES='-lkvm'
+ 	;;
+     nbsd*)
+-	NATDEPFILES='fork-child.o nat/fork-inferior.o inf-ptrace.o'
++	NATDEPFILES='fork-child.o nat/fork-inferior.o nat/netbsd-nat.o inf-ptrace.o'
+ 	HAVE_NATIVE_GCORE_HOST=1
+ 	;;
+     obsd*)
diff --git a/gdb-netbsd/patches/patch-gdb_nat_fork-inferior.c b/gdb-netbsd/patches/patch-gdb_nat_fork-inferior.c
new file mode 100644
index 0000000000..9e37bdcb25
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdb_nat_fork-inferior.c
@@ -0,0 +1,16 @@
+$NetBSD$
+
+--- gdb/nat/fork-inferior.c.orig	2020-08-26 18:57:35.000000000 +0000
++++ gdb/nat/fork-inferior.c
+@@ -526,7 +526,10 @@ startup_inferior (process_stratum_target
+ 
+ 	  case TARGET_WAITKIND_EXECD:
+ 	    /* Handle EXEC signals as if they were SIGTRAP signals.  */
+-	    xfree (ws.value.execd_pathname);
++	    /* Do not free the last execd pathname as it will be used in
++	       prepare_resume_reply(), after attaching a client side.  */
++	    if (pending_execs != 1)
++	      xfree (ws.value.execd_pathname);
+ 	    resume_signal = GDB_SIGNAL_TRAP;
+ 	    switch_to_thread (proc_target, event_ptid);
+ 	    break;
diff --git a/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.c b/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.c
new file mode 100644
index 0000000000..371b6260e8
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.c
@@ -0,0 +1,216 @@
+$NetBSD$
+
+--- gdb/nat/netbsd-nat.c.orig	2020-09-02 16:10:13.481373355 +0000
++++ gdb/nat/netbsd-nat.c
+@@ -0,0 +1,211 @@
++/* Internal interfaces for the NetBSD code.
++
++   Copyright (C) 2006-2020 Free Software Foundation, Inc.
++
++   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 "gdbsupport/common-defs.h"
++#include "nat/netbsd-nat.h"
++#include "gdbsupport/common-debug.h"
++
++#include <sys/types.h>
++#include <sys/ptrace.h>
++#include <sys/sysctl.h>
++
++#include "gdbsupport/function-view.h"
++
++namespace netbsd_nat
++{
++
++/* Return the executable file name of a process specified by PID.  Returns the
++   string in a static buffer.  */
++
++char *
++pid_to_exec_file (pid_t pid)
++{
++  static char buf[PATH_MAX];
++  int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
++  size_t buflen = sizeof (buf);
++  if (::sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
++    return NULL;
++  return buf;
++}
++
++/* Generic thread (LWP) lister within a specified process.  The callback
++   parameters is a C++ function that is called for each detected thread.  */
++
++static bool
++netbsd_thread_lister (const pid_t pid,
++		      gdb::function_view<bool (const struct kinfo_lwp *)>
++		      callback)
++{
++  int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0};
++  size_t size;
++
++  if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
++    perror_with_name (("sysctl"));
++
++  mib[4] = size / sizeof (size_t);
++
++  gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl
++    ((struct kinfo_lwp *) xcalloc (size, 1));
++
++  if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1
++      || size == 0)
++    perror_with_name (("sysctl"));
++
++  for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++)
++    {
++      struct kinfo_lwp *l = &kl[i];
++
++      /* Return true if the specified thread is alive.  */
++      auto lwp_alive
++	= [] (struct kinfo_lwp *lwp)
++	  {
++	    switch (lwp->l_stat)
++	      {
++	      case LSSLEEP:
++	      case LSRUN:
++	      case LSONPROC:
++	      case LSSTOP:
++	      case LSSUSPENDED:
++		return true;
++	      default:
++		return false;
++	      }
++	  };
++
++      /* Ignore embryonic or demised threads.  */
++      if (!lwp_alive (l))
++	continue;
++
++      if (callback (l))
++	return true;
++    }
++
++  return false;
++}
++
++/* Return true if PTID is still active in the inferior.  */
++
++bool
++thread_alive (ptid_t ptid)
++{
++  pid_t pid = ptid.pid ();
++  lwpid_t lwp = ptid.lwp ();
++
++  auto fn
++    = [&lwp] (const struct kinfo_lwp *kl)
++      {
++        return kl->l_lid == lwp;
++      };
++
++  return netbsd_thread_lister (pid, fn);
++}
++
++/* Return the name assigned to a thread by an application.  Returns
++   the string in a static buffer.  */
++
++const char *
++thread_name (ptid_t ptid)
++{
++  pid_t pid = ptid.pid ();
++  lwpid_t lwp = ptid.lwp ();
++
++  static char buf[KI_LNAMELEN] = {};
++
++  auto fn
++    = [&lwp] (const struct kinfo_lwp *kl)
++      {
++	if (kl->l_lid == lwp)
++	  {
++	    xsnprintf (buf, sizeof buf, "%s", kl->l_name);
++	    return true;
++	  }
++	return false;
++      };
++
++  if (netbsd_thread_lister (pid, fn))
++    return buf;
++  else
++    return NULL;
++}
++
++/* A generic thread lister within a specific PID.  The CALLBACK parameter
++   is a C++ function that is called for each detected thread.  */
++
++void
++list_threads (pid_t pid, gdb::function_view<void (ptid_t)> callback)
++{
++  auto fn
++    = [&callback, &pid] (const struct kinfo_lwp *kl)
++      {
++	ptid_t ptid = ptid_t (pid, kl->l_lid, 0);
++	callback (ptid);
++	return false;
++      };
++
++  netbsd_thread_lister (pid, fn);
++}
++
++/* Enable additional event reporting in a new process specified by PID.  */
++
++void
++enable_proc_events (pid_t pid)
++{
++  int events;
++
++  if (ptrace (PT_GET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
++    perror_with_name (("ptrace"));
++
++  events |= PTRACE_LWP_CREATE;
++  events |= PTRACE_LWP_EXIT;
++
++  if (ptrace (PT_SET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
++    perror_with_name (("ptrace"));
++}
++
++/* Implement reading and writing of inferior's siginfo_t specified by PID.
++   Returns -1 on failure and the number of bytes on a successful transfer.  */
++
++int
++qxfer_siginfo (pid_t pid, const char *annex, unsigned char *readbuf,
++	       unsigned const char *writebuf, CORE_ADDR offset, int len)
++{
++  ptrace_siginfo_t psi;
++
++  if (offset > sizeof (siginfo_t))
++    return -1;
++
++  if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
++    return -1;
++
++  if (offset + len > sizeof (siginfo_t))
++    len = sizeof (siginfo_t) - offset;
++
++  if (readbuf != NULL)
++    memcpy (readbuf, ((gdb_byte *) &psi.psi_siginfo) + offset, len);
++  else
++    {
++      memcpy (((gdb_byte *) &psi.psi_siginfo) + offset, writebuf, len);
++
++      if (ptrace (PT_SET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
++	return -1;
++    }
++  return len;
++}
++
++}
diff --git a/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.h b/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.h
new file mode 100644
index 0000000000..44460e15f6
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdb_nat_netbsd-nat.h
@@ -0,0 +1,52 @@
+$NetBSD$
+
+--- gdb/nat/netbsd-nat.h.orig	2020-09-02 16:10:13.481487586 +0000
++++ gdb/nat/netbsd-nat.h
+@@ -0,0 +1,47 @@
++/* Internal interfaces for the NetBSD code.
++
++   Copyright (C) 2006-2020 Free Software Foundation, Inc.
++
++   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 NAT_NETBSD_NAT_H
++#define NAT_NETBSD_NAT_H
++
++#include "gdbsupport/function-view.h"
++
++#include <unistd.h>
++
++namespace netbsd_nat
++{
++
++extern char *pid_to_exec_file (pid_t pid);
++
++extern bool thread_alive (ptid_t ptid);
++
++extern const char *thread_name (ptid_t ptid);
++
++extern void list_threads (pid_t pid,
++			  gdb::function_view<void (ptid_t)> callback);
++
++extern void enable_proc_events (pid_t pid);
++
++extern int qxfer_siginfo (pid_t pid, const char *annex, unsigned char *readbuf,
++			  unsigned const char *writebuf, CORE_ADDR offset,
++			  int len);
++
++}
++
++#endif
diff --git a/gdb-netbsd/patches/patch-gdb_nbsd-nat.c b/gdb-netbsd/patches/patch-gdb_nbsd-nat.c
new file mode 100644
index 0000000000..0498fb7f57
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdb_nbsd-nat.c
@@ -0,0 +1,236 @@
+$NetBSD$
+
+--- gdb/nbsd-nat.c.orig	2020-08-26 18:57:35.000000000 +0000
++++ gdb/nbsd-nat.c
+@@ -20,6 +20,7 @@
+ #include "defs.h"
+ 
+ #include "nbsd-nat.h"
++#include "nat/netbsd-nat.h"
+ #include "gdbthread.h"
+ #include "nbsd-tdep.h"
+ #include "inferior.h"
+@@ -36,13 +37,7 @@
+ char *
+ nbsd_nat_target::pid_to_exec_file (int pid)
+ {
+-  static char buf[PATH_MAX];
+-  size_t buflen;
+-  int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
+-  buflen = sizeof (buf);
+-  if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
+-    return NULL;
+-  return buf;
++  return netbsd_nat::pid_to_exec_file (pid);
+ }
+ 
+ /* Return the current directory for the process identified by PID.  */
+@@ -80,12 +75,12 @@ nbsd_pid_to_cmdline (int pid)
+   int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
+ 
+   size_t size = 0;
+-  if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
++  if (::sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
+     return nullptr;
+ 
+   gdb::unique_xmalloc_ptr<char[]> args (XNEWVAR (char, size));
+ 
+-  if (sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1
++  if (::sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1
+       || size == 0)
+     return nullptr;
+ 
+@@ -99,76 +94,12 @@ nbsd_pid_to_cmdline (int pid)
+   return args;
+ }
+ 
+-/* Generic thread (LWP) lister within a specified process.  The callback
+-   parameters is a C++ function that is called for each detected thread.  */
+-
+-static bool
+-nbsd_thread_lister (const pid_t pid,
+-		    gdb::function_view<bool (const struct kinfo_lwp *)>
+-		    callback)
+-{
+-  int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0};
+-  size_t size;
+-
+-  if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
+-    perror_with_name (("sysctl"));
+-
+-  mib[4] = size / sizeof (size_t);
+-
+-  gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl
+-    ((struct kinfo_lwp *) xcalloc (size, 1));
+-
+-  if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1
+-      || size == 0)
+-    perror_with_name (("sysctl"));
+-
+-  for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++)
+-    {
+-      struct kinfo_lwp *l = &kl[i];
+-
+-      /* Return true if the specified thread is alive.  */
+-      auto lwp_alive
+-	= [] (struct kinfo_lwp *lwp)
+-	  {
+-	    switch (lwp->l_stat)
+-	      {
+-	      case LSSLEEP:
+-	      case LSRUN:
+-	      case LSONPROC:
+-	      case LSSTOP:
+-	      case LSSUSPENDED:
+-		return true;
+-	      default:
+-		return false;
+-	      }
+-	  };
+-
+-      /* Ignore embryonic or demised threads.  */
+-      if (!lwp_alive (l))
+-	continue;
+-
+-      if (callback (l))
+-	return true;
+-    }
+-
+-  return false;
+-}
+-
+ /* Return true if PTID is still active in the inferior.  */
+ 
+ bool
+ nbsd_nat_target::thread_alive (ptid_t ptid)
+ {
+-  pid_t pid = ptid.pid ();
+-  int lwp = ptid.lwp ();
+-
+-  auto fn
+-    = [&lwp] (const struct kinfo_lwp *kl)
+-      {
+-        return kl->l_lid == lwp;
+-      };
+-
+-  return nbsd_thread_lister (pid, fn);
++  return netbsd_nat::thread_alive (ptid);
+ }
+ 
+ /* Return the name assigned to a thread by an application.  Returns
+@@ -178,26 +109,7 @@ const char *
+ nbsd_nat_target::thread_name (struct thread_info *thr)
+ {
+   ptid_t ptid = thr->ptid;
+-  pid_t pid = ptid.pid ();
+-  int lwp = ptid.lwp ();
+-
+-  static char buf[KI_LNAMELEN] = {};
+-
+-  auto fn
+-    = [&lwp] (const struct kinfo_lwp *kl)
+-      {
+-	if (kl->l_lid == lwp)
+-	  {
+-	    xsnprintf (buf, sizeof buf, "%s", kl->l_name);
+-	    return true;
+-	  }
+-	return false;
+-      };
+-
+-  if (nbsd_thread_lister (pid, fn))
+-    return buf;
+-  else
+-    return NULL;
++  return netbsd_nat::thread_name (ptid);
+ }
+ 
+ /* Implement the "post_attach" target_ops method.  */
+@@ -206,9 +118,8 @@ static void
+ nbsd_add_threads (nbsd_nat_target *target, pid_t pid)
+ {
+   auto fn
+-    = [&target, &pid] (const struct kinfo_lwp *kl)
++    = [&target] (ptid_t ptid)
+       {
+-	ptid_t ptid = ptid_t (pid, kl->l_lid, 0);
+ 	if (!in_thread_list (target, ptid))
+ 	  {
+ 	    if (inferior_ptid.lwp () == 0)
+@@ -216,27 +127,9 @@ nbsd_add_threads (nbsd_nat_target *targe
+ 	    else
+ 	      add_thread (target, ptid);
+ 	  }
+-	return false;
+       };
+ 
+-  nbsd_thread_lister (pid, fn);
+-}
+-
+-/* Enable additional event reporting on new processes.  */
+-
+-static void
+-nbsd_enable_proc_events (pid_t pid)
+-{
+-  int events;
+-
+-  if (ptrace (PT_GET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
+-    perror_with_name (("ptrace"));
+-
+-  events |= PTRACE_LWP_CREATE;
+-  events |= PTRACE_LWP_EXIT;
+-
+-  if (ptrace (PT_SET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
+-    perror_with_name (("ptrace"));
++  netbsd_nat::list_threads (pid, fn);
+ }
+ 
+ /* Implement the "post_startup_inferior" target_ops method.  */
+@@ -244,7 +137,7 @@ nbsd_enable_proc_events (pid_t pid)
+ void
+ nbsd_nat_target::post_startup_inferior (ptid_t ptid)
+ {
+-  nbsd_enable_proc_events (ptid.pid ());
++  netbsd_nat::enable_proc_events (ptid.pid ());
+ }
+ 
+ /* Implement the "post_attach" target_ops method.  */
+@@ -252,7 +145,7 @@ nbsd_nat_target::post_startup_inferior (
+ void
+ nbsd_nat_target::post_attach (int pid)
+ {
+-  nbsd_enable_proc_events (pid);
++  netbsd_nat::enable_proc_events (pid);
+   nbsd_add_threads (this, pid);
+ }
+ 
+@@ -861,26 +754,12 @@ nbsd_nat_target::xfer_partial (enum targ
+     {
+     case TARGET_OBJECT_SIGNAL_INFO:
+       {
+-	ptrace_siginfo_t psi;
+-
+-	if (offset > sizeof (siginfo_t))
+-	  return TARGET_XFER_E_IO;
++	len = netbsd_nat::qxfer_siginfo(pid, annex, readbuf, writebuf, offset,
++					len);
+ 
+-	if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
++	if (len == -1)
+ 	  return TARGET_XFER_E_IO;
+ 
+-	if (offset + len > sizeof (siginfo_t))
+-	  len = sizeof (siginfo_t) - offset;
+-
+-	if (readbuf != NULL)
+-	  memcpy (readbuf, ((gdb_byte *) &psi.psi_siginfo) + offset, len);
+-	else
+-	  {
+-	    memcpy (((gdb_byte *) &psi.psi_siginfo) + offset, writebuf, len);
+-
+-	    if (ptrace (PT_SET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
+-	      return TARGET_XFER_E_IO;
+-	  }
+ 	*xfered_len = len;
+ 	return TARGET_XFER_OK;
+       }
diff --git a/gdb-netbsd/patches/patch-gdbserver_configure.srv b/gdb-netbsd/patches/patch-gdbserver_configure.srv
index b01a058b80..966010839e 100644
--- a/gdb-netbsd/patches/patch-gdbserver_configure.srv
+++ b/gdb-netbsd/patches/patch-gdbserver_configure.srv
@@ -2,13 +2,14 @@ $NetBSD$
 
 --- gdbserver/configure.srv.orig	2020-08-26 18:57:35.000000000 +0000
 +++ gdbserver/configure.srv
-@@ -349,6 +349,12 @@ case "${gdbserver_host}" in
+@@ -349,6 +349,13 @@ case "${gdbserver_host}" in
  			srv_tgtobj="${srv_tgtobj} nat/windows-nat.o"
  			srv_tgtobj="${srv_tgtobj} arch/amd64.o arch/i386.o"
  			;;
 +  x86_64-*-netbsd*)	srv_regobj=""
 +			srv_tgtobj="netbsd-low.o netbsd-x86_64-low.o fork-child.o"
 +			srv_tgtobj="${srv_tgtobj} nat/fork-inferior.o"
++			srv_tgtobj="${srv_tgtobj} nat/netbsd-nat.o"
 +			srv_tgtobj="${srv_tgtobj} arch/amd64.o"
 +			srv_netbsd=yes
 +			;;
diff --git a/gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc b/gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc
index 64f4c0ded4..ad7500e88a 100644
--- a/gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc
+++ b/gdb-netbsd/patches/patch-gdbserver_netbsd-low.cc
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- gdbserver/netbsd-low.cc.orig	2020-08-27 02:43:00.926930485 +0000
+--- gdbserver/netbsd-low.cc.orig	2020-09-02 16:10:13.482445671 +0000
 +++ gdbserver/netbsd-low.cc
-@@ -0,0 +1,1598 @@
+@@ -0,0 +1,1352 @@
 +/* Copyright (C) 2020 Free Software Foundation, Inc.
 +
 +   This file is part of GDB.
@@ -23,6 +23,7 @@ $NetBSD$
 +#include "server.h"
 +#include "target.h"
 +#include "netbsd-low.h"
++#include "nat/netbsd-nat.h"
 +
 +#include <sys/param.h>
 +#include <sys/types.h>
@@ -36,6 +37,9 @@ $NetBSD$
 +
 +#include <elf.h>
 +
++#include <type_traits>
++
++#include "gdbsupport/eintr.h"
 +#include "gdbsupport/gdb_wait.h"
 +#include "gdbsupport/filestuff.h"
 +#include "gdbsupport/common-inferior.h"
@@ -46,55 +50,15 @@ $NetBSD$
 +
 +const struct target_desc *netbsd_tdesc;
 +
-+/* Per-process private data.  */
-+
-+struct process_info_private
-+{
-+  /* The PTID obtained from the last wait performed on this process.
-+     Initialized to null_ptid until the first wait is performed.  */
-+  ptid_t last_wait_event_ptid;
-+
-+  /* &_r_debug.  0 if not yet determined.  -1 if no PT_DYNAMIC in Phdrs.  */
-+  CORE_ADDR r_debug;
-+};
-+
-+/* Build a ptid_t given a PID and a NetBSD TID.  */
-+
-+static ptid_t
-+netbsd_ptid_t (pid_t pid, lwpid_t tid)
-+{
-+  return ptid_t (pid, tid, 0);
-+}
-+
-+/* A wrapper around waitpid that handles the various idiosyncrasies
-+   of NetBSD waitpid.  */
-+
-+static int
-+netbsd_waitpid (int pid, int *stat_loc, int options)
-+{
-+  int ret;
-+
-+  do
-+    {
-+      ret = waitpid (pid, stat_loc, options);
-+    }
-+  while (ret == -1 && errno == EINTR);
-+
-+  return ret;
-+}
-+
 +/* Call add_process with the given parameters, and initializes
 +   the process' private data.  */
 +
 +static struct process_info *
 +netbsd_add_process (int pid, int attached)
 +{
-+  struct process_info *proc;
-+
-+  proc = add_process (pid, attached);
++  struct process_info *proc = add_process (pid, attached);
 +  proc->tdesc = netbsd_tdesc;
-+  proc->priv = XCNEW (struct process_info_private);
-+  proc->priv->last_wait_event_ptid = null_ptid;
++  proc->priv = nullptr;
 +
 +  return proc;
 +}
@@ -107,10 +71,10 @@ $NetBSD$
 +  /* Switch child to its own process group so that signals won't
 +     directly affect GDBserver. */
 +  if (setpgid (0, 0) < 0)
-+    trace_start_error_with_name ("setpgid");
++    trace_start_error_with_name (("setpgid"));
 +
-+  if (ptrace (PT_TRACE_ME, 0, NULL, 0) < 0)
-+    trace_start_error_with_name ("ptrace");
++  if (ptrace (PT_TRACE_ME, 0, nullptr, 0) < 0)
++    trace_start_error_with_name (("ptrace"));
 +
 +  /* If GDBserver is connected to gdb via stdio, redirect the inferior's
 +     stdout to stderr so that inferior i/o doesn't corrupt the connection.
@@ -118,11 +82,11 @@ $NetBSD$
 +  if (remote_connection_is_stdio ())
 +    {
 +      if (close (0) < 0)
-+	trace_start_error_with_name ("close");
++	trace_start_error_with_name (("close"));
 +      if (open ("/dev/null", O_RDONLY) < 0)
-+	trace_start_error_with_name ("open");
++	trace_start_error_with_name (("open"));
 +      if (dup2 (2, 1) < 0)
-+	trace_start_error_with_name ("dup2");
++	trace_start_error_with_name (("dup2"));
 +      if (write (2, "stdin/stdout redirected\n",
 +		 sizeof ("stdin/stdout redirected\n") - 1) < 0)
 +	{
@@ -131,87 +95,18 @@ $NetBSD$
 +    }
 +}
 +
-+static void
-+netbsd_add_threads_sysctl (pid_t pid)
-+{
-+  struct kinfo_lwp *kl;
-+  int mib[5];
-+  size_t i, nlwps;
-+  size_t size;
-+
-+  mib[0] = CTL_KERN;
-+  mib[1] = KERN_LWP;
-+  mib[2] = pid;
-+  mib[3] = sizeof (struct kinfo_lwp);
-+  mib[4] = 0;
-+
-+  if (sysctl (mib, 5, NULL, &size, NULL, 0) == -1 || size == 0)
-+    trace_start_error_with_name ("sysctl");
-+
-+  mib[4] = size / sizeof(size_t);
-+
-+  kl = (struct kinfo_lwp *) xmalloc (size);
-+  if (kl == NULL)
-+    trace_start_error_with_name ("malloc");
-+
-+  if (sysctl (mib, 5, kl, &size, NULL, 0) == -1 || size == 0)
-+    trace_start_error_with_name ("sysctl");
-+
-+  nlwps = size / sizeof (struct kinfo_lwp);
-+
-+  for (i = 0; i < nlwps; i++) {
-+    ptid_t ptid = netbsd_ptid_t (pid, kl[i].l_lid);
-+    add_thread (ptid, NULL);
-+  }
-+
-+  xfree(kl);
-+}
++/* Register threads in the process specified by PID.  */
 +
 +static void
-+netbsd_wait_stopped_noreap (pid_t pid)
++netbsd_add_threads (pid_t pid)
 +{
-+  int status;
-+
-+  gdb_assert (pid > 0);
-+
-+repeat:
-+  pid_t wpid = netbsd_waitpid (pid, &status, WNOWAIT);
-+
-+  if (wpid == -1 || wpid != pid)
-+    internal_error (__FILE__, __LINE__,
-+		    _("unexpected waitpid return value %d"), wpid);
-+
-+  if (WIFSTOPPED (status))
-+    return;
-+
-+  if (WIFSIGNALED (status) || WIFEXITED (status))
-+    internal_error (__FILE__, __LINE__, _("tracee died"));
-+
-+  /* Should not happen.  */
-+  if (WIFCONTINUED (status))
-+    goto repeat;
-+
-+  __unreachable();
-+}
-+
-+/* Assuming we've just attached to a stopped and waited inferior whose pid is PID */
-+
-+static void
-+netbsd_add_threads_after_attach (pid_t pid)
-+{
-+  struct ptrace_lwpstatus pl;
-+
-+  pl.pl_lwpid = 0;
-+  while (ptrace (PT_LWPNEXT, pid, (void *)&pl, sizeof (pl)) != -1 &&
-+    pl.pl_lwpid != 0)
-+    {
-+      ptid_t thread_ptid = netbsd_ptid_t (pid, pl.pl_lwpid);
++  auto fn
++    = [] (ptid_t ptid)
++      {
++	add_thread (ptid, nullptr);
++      };
 +
-+      if (!find_thread_ptid (thread_ptid))
-+	{
-+	  add_thread (thread_ptid, NULL);
-+	}
-+    }
++  netbsd_nat::list_threads (pid, fn);
 +}
 +
 +/* Implement the create_inferior method of the target_ops vector.  */
@@ -222,361 +117,360 @@ $NetBSD$
 +{
 +  std::string str_program_args = construct_inferior_arguments (program_args);
 +
-+  pid_t pid = fork_inferior (program,
-+			     str_program_args.c_str (),
++  pid_t pid = fork_inferior (program, str_program_args.c_str (),
 +			     get_environ ()->envp (), netbsd_ptrace_fun,
-+			     NULL, NULL, NULL, NULL);
++			     nullptr, nullptr, nullptr, nullptr);
 +
 +  netbsd_add_process (pid, 0);
 +
-+  netbsd_wait_stopped_noreap (pid);
-+
-+  netbsd_add_threads_sysctl (pid);
-+
 +  post_fork_inferior (pid, program);
 +
 +  return pid;
 +}
 +
++/* Implement the post_create_inferior target_ops method.  */
++
++void
++netbsd_process_target::post_create_inferior ()
++{
++  pid_t pid = current_process ()->pid;
++  netbsd_nat::enable_proc_events (pid);
++}
++
 +/* Implement the attach target_ops method.  */
 +
 +int
 +netbsd_process_target::attach (unsigned long pid)
 +{
 +
-+  if (ptrace (PT_ATTACH, pid, NULL, 0) != 0)
++  if (ptrace (PT_ATTACH, pid, nullptr, 0) != 0)
 +    error ("Cannot attach to process %lu: %s (%d)\n", pid,
-+	   safe_strerror (errno), errno);
++	    safe_strerror (errno), errno);
 +
 +  netbsd_add_process (pid, 1);
-+  netbsd_add_threads_after_attach (pid);
++  netbsd_nat::enable_proc_events (pid);
++  netbsd_add_threads (pid);
 +
 +  return 0;
 +}
 +
++/* Returns true if GDB is interested in any child syscalls.  */
++
++static bool
++gdb_catching_syscalls_p (pid_t pid)
++{
++  struct process_info *proc = find_process_pid (pid);
++  return !proc->syscalls_to_catch.empty ();
++}
++
 +/* Implement the resume target_ops method.  */
 +
 +void
 +netbsd_process_target::resume (struct thread_resume *resume_info, size_t n)
 +{
-+  ptid_t ptid = resume_info[0].thread;
++  ptid_t resume_ptid = resume_info[0].thread;
 +  const int signal = resume_info[0].sig;
++  const bool step = resume_info[0].kind == resume_step;
++  
++  if (resume_ptid == minus_one_ptid)
++    resume_ptid = ptid_of (current_thread);
 +
-+  if (ptid == minus_one_ptid)
-+    ptid = ptid_of (current_thread);
++  const pid_t pid = resume_ptid.pid ();
++  const lwpid_t lwp = resume_ptid.lwp ();
++  regcache_invalidate_pid (pid);
 +
-+  regcache_invalidate_pid (ptid.pid ());
++  auto fn
++    = [&] (ptid_t ptid)
++      {
++	if (step)
++	  {
++	    if (ptid.lwp () == lwp || n != 1)
++	      {
++		if (ptrace (PT_SETSTEP, pid, NULL, ptid.lwp ()) == -1)
++		  perror_with_name (("ptrace"));
++		if (ptrace (PT_RESUME, pid, NULL, ptid.lwp ()) == -1)
++		  perror_with_name (("ptrace"));
++	      }
++	    else
++	      {
++		if (ptrace (PT_CLEARSTEP, pid, NULL, ptid.lwp ()) == -1)
++		  perror_with_name (("ptrace"));
++		if (ptrace (PT_SUSPEND, pid, NULL, ptid.lwp ()) == -1)
++		  perror_with_name (("ptrace"));
++	      }
++	  }
++	else
++	  {
++	    if (ptrace (PT_CLEARSTEP, pid, NULL, ptid.lwp ()) == -1)
++	      perror_with_name (("ptrace"));
++	    if (ptrace (PT_RESUME, pid, NULL, ptid.lwp ()) == -1)
++	      perror_with_name (("ptrace"));
++	  }
++      };
 +
-+  if (resume_info[0].kind == resume_step)
-+    {
-+      if (n == 1)
-+	{
-+	  struct ptrace_lwpstatus pl;
-+	  int val;
-+	  pl.pl_lwpid = 0;
-+	  while ((val = ptrace (PT_LWPNEXT, ptid.pid(), (void *)&pl,
-+	    sizeof(pl))) != -1 && pl.pl_lwpid != 0)
-+	   {
-+	      if (pl.pl_lwpid == ptid.lwp())
-+		{
-+		  ptrace (PT_SETSTEP, ptid.pid(), NULL, pl.pl_lwpid);
-+		  ptrace (PT_RESUME, ptid.pid(), NULL, pl.pl_lwpid);
-+		}
-+	      else
-+		{
-+		  ptrace (PT_CLEARSTEP, ptid.pid(), NULL, pl.pl_lwpid);
-+		  ptrace (PT_SUSPEND, ptid.pid(), NULL, pl.pl_lwpid);
-+		}
-+	   }
-+	}
-+      else
-+	{
-+	  struct ptrace_lwpstatus pl;
-+	  int val;
-+	  pl.pl_lwpid = 0;
-+	  while ((val = ptrace (PT_LWPNEXT, ptid.pid(), (void *)&pl,
-+	    sizeof(pl))) != -1 && pl.pl_lwpid != 0)
-+	   {
-+	      ptrace (PT_SETSTEP, ptid.pid(), NULL, pl.pl_lwpid);
-+	      ptrace (PT_RESUME, ptid.pid(), NULL, pl.pl_lwpid);
-+	   }
-+	}
-+    }
-+  else
-+    {
-+      struct ptrace_lwpstatus pl;
-+      int val;
-+      pl.pl_lwpid = 0;
-+      while ((val = ptrace (PT_LWPNEXT, ptid.pid(), (void *)&pl, sizeof(pl))) != -1 &&
-+	pl.pl_lwpid != 0)
-+	{
-+	  ptrace (PT_CLEARSTEP, ptid.pid(), NULL, pl.pl_lwpid);
-+	  ptrace (PT_RESUME, ptid.pid(), NULL, pl.pl_lwpid);
-+	}
-+    }
++  netbsd_nat::list_threads (pid, fn);
++
++  int request = gdb_catching_syscalls_p (pid) ? PT_CONTINUE : PT_SYSCALL;
 +
 +  errno = 0;
-+  ptrace (PT_CONTINUE, ptid.pid(), (void *)1, signal);
++  ptrace (request, pid, (void *)1, signal);
 +  if (errno)
-+    perror_with_name ("ptrace");
++    perror_with_name (("ptrace"));
 +}
 +
-+static char *
-+netbsd_pid_to_exec_file (pid_t pid)
++/* Returns true if GDB is interested in the reported SYSNO syscall.  */
++
++static bool
++netbsd_catch_this_syscall (int sysno)
 +{
-+  static const int name[] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
-+  static char path[MAXPATHLEN];
-+  size_t len;
++  struct process_info *proc = current_process ();
++
++  if (proc->syscalls_to_catch.empty ())
++    return false;
 +
-+  len = sizeof (path);
-+  if (sysctl (name, __arraycount(name), path, &len, NULL, 0) == -1)
-+    return NULL;
++  if (proc->syscalls_to_catch[0] == ANY_SYSCALL)
++    return true;
 +
-+  return path;
++  for (int iter : proc->syscalls_to_catch)
++    if (iter == sysno)
++      return true;
++
++  return false;
 +}
 +
++/* Helper function for child_wait and the derivatives of child_wait.
++   HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
++   translation of that in OURSTATUS.  */
 +static void
-+netbsd_enable_event_reporting (pid_t pid)
++netbsd_store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus)
 +{
-+  ptrace_event_t event;
-+
-+  ptrace (PT_GET_EVENT_MASK, pid, &event, sizeof (event));
-+
-+  event.pe_set_event |= PTRACE_LWP_CREATE;
-+  event.pe_set_event |= PTRACE_LWP_EXIT;
-+
-+  ptrace (PT_SET_EVENT_MASK, pid, &event, sizeof (event));
++  if (WIFEXITED (hoststatus))
++    {
++      ourstatus->kind = TARGET_WAITKIND_EXITED;
++      ourstatus->value.integer = WEXITSTATUS (hoststatus);
++    }
++  else if (!WIFSTOPPED (hoststatus))
++    {
++      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
++      ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (hoststatus));
++    }
++  else
++    {
++      ourstatus->kind = TARGET_WAITKIND_STOPPED;
++      ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (hoststatus));
++    }
 +}
 +
-+/* Implement the wait target_ops method.  */
++/* Implement a safe wrapper around waitpid().  */
 +
-+static ptid_t
-+netbsd_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus, int target_options)
++static pid_t
++netbsd_waitpid (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 +{
-+  pid_t pid;
 +  int status;
 +
-+  if (ptid == minus_one_ptid)
-+    ptid = ptid_of (current_thread);
++  pid_t pid = gdb::handle_eintr (::waitpid, ptid.pid (), &status, options);
 +
-+  pid = ptid.pid();
++  if (pid == -1)
++    perror_with_name (_("Child process unexpectedly missing"));
++
++  netbsd_store_waitstatus (ourstatus, status);
++  return pid;
++}
 +
-+  int options = 0;
-+  if (target_options & TARGET_WNOHANG)
-+    options |= WNOHANG;
 +
-+  pid_t wpid = netbsd_waitpid (pid, &status, options);
++/* Implement the wait target_ops method.
++
++   Wait for the child specified by PTID to do something.  Return the
++   process ID of the child, or MINUS_ONE_PTID in case of error; store
++   the status in *OURSTATUS.  */
++
++static ptid_t
++netbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus,
++	     int target_options)
++{ 
++  pid_t pid = netbsd_waitpid (ptid, ourstatus, target_options);
++  ptid_t wptid = ptid_t (pid);
 +
-+  if (wpid == 0)
++  if (pid == 0)
 +    {
 +      gdb_assert (target_options & TARGET_WNOHANG);
 +      ourstatus->kind = TARGET_WAITKIND_IGNORE;
 +      return null_ptid;
 +    }
 +
-+  gdb_assert (wpid != -1);
++  gdb_assert (pid != -1);
 +
-+  if (WIFEXITED (status))
-+    {
-+      ourstatus->kind = TARGET_WAITKIND_EXITED;
-+      ourstatus->value.integer = WEXITSTATUS (status);
-+      return ptid;
-+    }
++  /* If the child stopped, keep investigating its status.  */
++  if (ourstatus->kind != TARGET_WAITKIND_STOPPED)
++    return wptid;
 +
-+  if (WIFSIGNALED (status))
-+    {
-+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
-+      ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (status));
-+      return ptid;
-+    }
++  /* Extract the event and thread that received a signal.  */
++  ptrace_siginfo_t psi;
++  if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
++    perror_with_name (("ptrace"));
 +
-+  if (WIFCONTINUED(status))
-+    {
-+      ourstatus->kind = TARGET_WAITKIND_IGNORE;
-+      return null_ptid;
-+    }
++  /* Pick child's siginfo_t.  */
++  siginfo_t *si = &psi.psi_siginfo;
 +
++  lwpid_t lwp = psi.psi_lwpid;
 +
-+  if (WIFSTOPPED (status))
-+    {
-+      ptrace_state_t pst;
-+      ptrace_siginfo_t psi, child_psi;
-+      pid_t child, wchild;
-+      ptid_t child_ptid;
-+      lwpid_t lwp;
++  int signo = si->si_signo;
++  const int code = si->si_code;
 +
-+      {
-+	struct process_info *proc;
++  /* Construct PTID with a specified thread that received the event.
++     If a signal was targeted to the whole process, lwp is 0.  */
++  wptid = ptid_t (pid, lwp, 0);
 +
-+      /* Architecture-specific setup after inferior is running.  */
-+      proc = find_process_pid (wpid);
-+      if (proc->tdesc == NULL)
-+	{
-+	      /* This needs to happen after we have attached to the
-+		 inferior and it is stopped for the first time, but
-+		 before we access any inferior registers.  */
-+	      the_low_target.arch_setup ();
-+	}
-+      }
++  /* Bail out on non-debugger oriented signals..  */
++  if (signo != SIGTRAP)
++    return wptid;
 +
-+      ourstatus->kind = TARGET_WAITKIND_STOPPED;
-+      ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (status));
++  /* Stop examining non-debugger oriented SIGTRAP codes.  */
++  if (code <= SI_USER || code == SI_NOINFO)
++    return wptid;
 +
-+      // Find the lwp that caused the wait status change
-+      if (ptrace (PT_GET_SIGINFO, wpid, &psi, sizeof(psi)) == -1)
++  /* Process state for threading events */
++  ptrace_state_t pst = {};
++  if (code == TRAP_LWP)
++    {
++      if (ptrace (PT_GET_PROCESS_STATE, pid, &pst, sizeof (pst)) == -1)
 +	perror_with_name (("ptrace"));
++    }
 +
-+      /* For whole-process signals pick random thread */
-+      if (psi.psi_lwpid == 0)
-+	{
-+	  // XXX: Is this always valid?
-+	  lwp = lwpid_of (current_thread);
-+	}
++  if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_EXIT)
++    {
++      /* If GDB attaches to a multi-threaded process, exiting
++	 threads might be skipped during post_attach that
++	 have not yet reported their PTRACE_LWP_EXIT event.
++	 Ignore exited events for an unknown LWP.  */
++      thread_info *thr = find_thread_ptid (wptid);
++      if (thr == nullptr)
++	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
 +      else
 +	{
-+	  lwp = psi.psi_lwpid;
++	  ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
++	  /* NetBSD does not store an LWP exit status.  */
++	  ourstatus->value.integer = 0;
++
++	  remove_thread (thr);
 +	}
++      return wptid;
++    }
 +
-+      ptid_t wptid = netbsd_ptid_t (wpid, lwp);
++  if (find_thread_ptid (ptid_t (pid)))
++    current_thread = find_thread_ptid (wptid);
 +
-+      if (!find_thread_ptid (wptid))
++  if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_CREATE)
++    {
++      /* If GDB attaches to a multi-threaded process, newborn
++	 threads might be added by nbsd_add_threads that have
++	 not yet reported their PTRACE_LWP_CREATE event.  Ignore
++	 born events for an already-known LWP.  */
++      if (find_thread_ptid (wptid))
++	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
++      else
 +	{
 +	  add_thread (wptid, NULL);
++	  ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED;
 +	}
++      return wptid;
++    }
 +
-+      switch (psi.psi_siginfo.si_signo)
++  if (code == TRAP_EXEC)
++    {
++      ourstatus->kind = TARGET_WAITKIND_EXECD;
++      ourstatus->value.execd_pathname
++	= xstrdup (netbsd_nat::pid_to_exec_file (pid));
++      return wptid;
++    }
++
++  if (code == TRAP_TRACE)
++    {
++      return wptid;
++    }
++
++  if (code == TRAP_SCE || code == TRAP_SCX)
++    {
++      int sysnum = si->si_sysnum;
++
++      if (!netbsd_catch_this_syscall(sysnum))
 +	{
-+	case SIGTRAP:
-+	  switch (psi.psi_siginfo.si_code)
-+	    {
-+	    case TRAP_BRKPT:
++	  /* If the core isn't interested in this event, ignore it.  */
++	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
++	  return wptid;
++	}
++
++      ourstatus->kind =
++	(code == TRAP_SCE) ? TARGET_WAITKIND_SYSCALL_ENTRY :
++	TARGET_WAITKIND_SYSCALL_RETURN;
++      ourstatus->value.syscall_number = sysnum;
++      return wptid;
++    }
++
++  if (code == TRAP_BRKPT)
++    {
 +#ifdef PTRACE_BREAKPOINT_ADJ
-+	      {
-+		CORE_ADDR pc;
-+		struct reg r;
-+		ptrace (PT_GETREGS, wpid, &r, psi.psi_lwpid);
-+		pc = PTRACE_REG_PC (&r);
-+		PTRACE_REG_SET_PC (&r, pc - PTRACE_BREAKPOINT_ADJ);
-+		ptrace (PT_SETREGS, wpid, &r, psi.psi_lwpid);
-+	      }
-+#endif
-+	    case TRAP_DBREG:
-+	    case TRAP_TRACE:
-+	      /* These stop reasons return STOPPED and are distinguished later */
-+	      break;
-+	    case TRAP_SCE:
-+	      ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
-+	      ourstatus->value.syscall_number = psi.psi_siginfo.si_sysnum;
-+	      break;
-+	    case TRAP_SCX:
-+	      ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
-+	      ourstatus->value.syscall_number = psi.psi_siginfo.si_sysnum;
-+	      break;
-+#if 0
-+	    case TRAP_EXEC:
-+	      ourstatus->kind = TARGET_WAITKIND_EXECD;
-+	      ourstatus->value.execd_pathname = xstrdup(netbsd_pid_to_exec_file (wpid));
-+	      break;
++      CORE_ADDR pc;
++      struct reg r;
++      ptrace (PT_GETREGS, pid, &r, psi.psi_lwpid);
++      pc = PTRACE_REG_PC (&r);
++      PTRACE_REG_SET_PC (&r, pc - PTRACE_BREAKPOINT_ADJ);
++      ptrace (PT_SETREGS, pid, &r, psi.psi_lwpid);
 +#endif
-+	    case TRAP_LWP:
-+	    case TRAP_CHLD:
-+	      if (ptrace (PT_GET_PROCESS_STATE, wpid, &pst, sizeof(pst)) == -1)
-+		perror_with_name (("ptrace"));
-+	      switch (pst.pe_report_event)
-+		{
-+		case PTRACE_FORK:
-+		case PTRACE_VFORK:
-+		  if (pst.pe_report_event == PTRACE_FORK)
-+		    ourstatus->kind = TARGET_WAITKIND_FORKED;
-+		  else
-+		    ourstatus->kind = TARGET_WAITKIND_VFORKED;
-+		  child = pst.pe_other_pid;
-+
-+		  wchild = netbsd_waitpid (child, &status, 0);
-+
-+		  if (wchild == -1)
-+		    perror_with_name (("waitpid"));
-+
-+		  gdb_assert (wchild == child);
-+
-+		  if (!WIFSTOPPED(status))
-+		    {
-+		      /* Abnormal situation (SIGKILLed?).. bail out */
-+		      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-+		      return wptid;
-+		    }
-+
-+		  if (ptrace (PT_GET_SIGINFO, child, &child_psi, sizeof(child_psi)) == -1)
-+		    perror_with_name (("ptrace"));
-+
-+		  if (child_psi.psi_siginfo.si_signo != SIGTRAP)
-+		    {
-+		      /* Abnormal situation.. bail out */
-+		      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-+		      return wptid;
-+		    }
-+
-+		  if (child_psi.psi_siginfo.si_code != TRAP_CHLD)
-+		    {
-+		      /* Abnormal situation.. bail out */
-+		      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-+		      return wptid;
-+		    }
-+
-+		  child_ptid = netbsd_ptid_t (child, child_psi.psi_lwpid);
-+		  netbsd_enable_event_reporting (child_ptid.pid ());
-+		  ourstatus->value.related_pid = child_ptid;
-+		  break;
-+		case PTRACE_VFORK_DONE:
-+		  ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
-+		  break;
-+		case PTRACE_LWP_CREATE:
-+		  wptid = netbsd_ptid_t (wpid, pst.pe_lwp);
-+		  if (!find_thread_ptid (wptid))
-+		    {
-+		      add_thread (wptid, NULL);
-+		    }
-+		  ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED;
-+		  break;
-+		case PTRACE_LWP_EXIT:
-+		  wptid = netbsd_ptid_t (wpid, pst.pe_lwp);
-+		  thread_info *thread = find_thread_ptid (wptid);
-+		  if (!thread)
-+		    {
-+		      /* Dead child reported after attach? */
-+		      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-+		      return wptid;
-+		    }
-+		  remove_thread (thread);
-+		  ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
-+
-+#if 0
-+		  if (ptrace (PT_CONTINUE, pid, (void *)1, 0) == -1)
-+		    perror_with_name (("ptrace"));
-+#endif
-+		  break;
-+		}
-+	      break;
-+	    }
-+	  break;
-+	}
 +      return wptid;
 +    }
 +
-+  return null_ptid;
++  /* Unclassified SIGTRAP event.  */
++  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
++  return wptid;
 +}
 +
-+/* A wrapper around netbsd_wait_1 that also prints debug traces when
-+   such debug traces have been activated.  */
++/* Implement the wait target_ops method.  */
 +
 +ptid_t
-+netbsd_process_target::wait (ptid_t ptid, struct target_waitstatus *status, int options)
++netbsd_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
++			     int target_options)
 +{
-+  ptid_t new_ptid;
-+
-+  new_ptid = netbsd_wait_1 (ptid, status, options);
-+
-+  return new_ptid;
++  while (true)
++    {
++      ptid_t wptid = netbsd_wait (ptid, ourstatus, target_options);
++
++      /* Register thread in the gdbcore if a thread was not reported earlier.
++	 This is required after ::create_inferior, when the gdbcore does not
++	 know about the first internal thread.
++	 This may also happen on attach, when an event is registered on a thread
++	 that was not fully initialized during the attach stage. */
++      if (wptid.lwp () != 0 && !find_thread_ptid (wptid)
++	  && ourstatus->kind != TARGET_WAITKIND_THREAD_EXITED)
++	add_thread (wptid, nullptr);
++
++      switch (ourstatus->kind)
++	{
++	case TARGET_WAITKIND_EXITED:
++	case TARGET_WAITKIND_STOPPED:
++	case TARGET_WAITKIND_SIGNALLED:
++	case TARGET_WAITKIND_FORKED:
++	case TARGET_WAITKIND_VFORKED:
++	case TARGET_WAITKIND_EXECD:
++	case TARGET_WAITKIND_VFORK_DONE:
++	case TARGET_WAITKIND_SYSCALL_ENTRY:
++	case TARGET_WAITKIND_SYSCALL_RETURN:
++	  /* Pass the result to the generic code.  */
++	  return wptid;
++	case TARGET_WAITKIND_THREAD_CREATED:
++	case TARGET_WAITKIND_THREAD_EXITED:
++	  /* The core needlessly stops on these events.  */
++	  /* FALLTHROUGH */
++	case TARGET_WAITKIND_SPURIOUS:
++	  /* Spurious events are unhandled by the gdbserver core.  */
++	  if (ptrace (PT_CONTINUE, current_process ()->pid, (void *) 1, 0)
++	      == -1)
++	    perror_with_name (("ptrace"));
++	  break;
++	default:
++	  error (("Unknwon stopped status"));
++	}
++    }
 +}
 +
 +/* Implement the kill target_ops method.  */
@@ -585,12 +479,11 @@ $NetBSD$
 +netbsd_process_target::kill (process_info *process)
 +{
 +  pid_t pid = process->pid;
-+  ptid_t ptid = netbsd_ptid_t (pid, 0);
-+  struct target_waitstatus status;
++  ptrace (PT_KILL, pid, nullptr, 0);
 +
-+  ptrace (PT_KILL, pid, NULL, 0);
-+  wait (ptid, &status, 0);
-+  the_target->mourn (process);
++  int status;
++  gdb::handle_eintr (::waitpid, pid, &status, 0);
++  mourn (process);
 +  return 0;
 +}
 +
@@ -601,8 +494,8 @@ $NetBSD$
 +{
 +  pid_t pid = process->pid;
 +
-+  ptrace (PT_DETACH, pid, (void *)1, 0);
-+  the_target->mourn (process);
++  ptrace (PT_DETACH, pid, (void *) 1, 0);
++  mourn (process);
 +  return 0;
 +}
 +
@@ -613,10 +506,6 @@ $NetBSD$
 +{
 +  for_each_thread (proc->pid, remove_thread);
 +
-+  /* Free our private data.  */
-+  free (proc->priv);
-+  proc->priv = NULL;
-+
 +  remove_process (proc);
 +}
 +
@@ -634,9 +523,7 @@ $NetBSD$
 +bool
 +netbsd_process_target::thread_alive (ptid_t ptid)
 +{
-+  /* The list of threads is updated at the end of each wait, so it
-+     should be up to date.  No need to re-fetch it.  */
-+  return (find_thread_ptid (ptid) != NULL);
++  return netbsd_nat::thread_alive (ptid);
 +}
 +
 +/* Implement the fetch_registers target_ops method.  */
@@ -649,14 +536,11 @@ $NetBSD$
 +
 +  while (regset->size >= 0)
 +    {
-+      char *buf;
-+      int res;
-+
-+      buf = (char *)xmalloc (regset->size);
-+      res = ptrace (regset->get_request, inferior_ptid.pid(), buf,
-+		    inferior_ptid.lwp());
-+      if (res < 0)
-+	perror ("ptrace");
++      char *buf = (char *) xmalloc (regset->size);
++      int res = ptrace (regset->get_request, inferior_ptid.pid (), buf,
++			inferior_ptid.lwp ());
++      if (res == -1)
++	perror_with_name (("ptrace"));
 +      regset->store_function (regcache, buf);
 +      free (buf);
 +      regset++;
@@ -673,22 +557,19 @@ $NetBSD$
 +
 +  while (regset->size >= 0)
 +    {
-+      char *buf;
-+      int res;
-+
-+      buf = (char *)xmalloc (regset->size);
-+      res = ptrace (regset->get_request, inferior_ptid.pid(), buf,
-+		    inferior_ptid.lwp());
++      char *buf = (char *)xmalloc (regset->size);
++      int res = ptrace (regset->get_request, inferior_ptid.pid (), buf,
++			inferior_ptid.lwp ());
++      if (res == -1)
++	perror_with_name (("ptrace"));
 +      if (res == 0)
 +	{
 +	  /* Then overlay our cached registers on that.  */
 +	  regset->fill_function (regcache, buf);
 +	  /* Only now do we write the register set.  */
-+	  res = ptrace (regset->set_request, inferior_ptid.pid(), buf,
-+			inferior_ptid.lwp());
++	  res = ptrace (regset->set_request, inferior_ptid.pid (), buf,
++			inferior_ptid.lwp ());
 +	}
-+      if (res < 0)
-+	perror ("ptrace");
 +      free (buf);
 +      regset++;
 +    }
@@ -704,7 +585,7 @@ $NetBSD$
 +  io.piod_op = PIOD_READ_D;
 +  io.piod_len = size;
 +
-+  ptid_t inferior_ptid = ptid_of (current_thread);
++  pid_t pid = current_process ()->pid;
 +
 +  int bytes_read = 0;
 +
@@ -718,7 +599,7 @@ $NetBSD$
 +      io.piod_offs = (void *)(memaddr + bytes_read);
 +      io.piod_addr = myaddr + bytes_read;
 +
-+      int rv = ptrace (PT_IO, inferior_ptid.pid(), &io, 0);
++      int rv = ptrace (PT_IO, pid, &io, 0);
 +      if (rv == -1)
 +	return errno;
 +      if (io.piod_len == 0)
@@ -742,7 +623,7 @@ $NetBSD$
 +  io.piod_op = PIOD_WRITE_D;
 +  io.piod_len = size;
 +
-+  ptid_t inferior_ptid = ptid_of (current_thread);
++  pid_t pid = current_process ()->pid;
 +
 +  int bytes_written = 0;
 +
@@ -757,7 +638,7 @@ $NetBSD$
 +      io.piod_addr = (void *)(myaddr + bytes_written);
 +      io.piod_offs = (void *)(memaddr + bytes_written);
 +
-+      int rv = ptrace (PT_IO, inferior_ptid.pid(), &io, 0);
++      int rv = ptrace (PT_IO, pid, &io, 0);
 +      if (rv == -1)
 +	return errno;
 +      if (io.piod_len == 0)
@@ -781,43 +662,47 @@ $NetBSD$
 +  ::kill (inferior_ptid.pid(), SIGINT);
 +}
 +
-+/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
-+   to debugger memory starting at MYADDR.  */
-+
-+int
-+netbsd_process_target::read_auxv (CORE_ADDR offset,
-+				  unsigned char *myaddr, unsigned int len)
++static size_t
++netbsd_read_auxv(pid_t pid, void *offs, void *addr, size_t len)
 +{
-+
 +  struct ptrace_io_desc pio;
-+  pid_t pid = pid_of (current_thread);
 +
 +  pio.piod_op = PIOD_READ_AUXV;
-+  pio.piod_offs = (void *)(intptr_t)offset;
-+  pio.piod_addr = myaddr;
++  pio.piod_offs = offs;
++  pio.piod_addr = addr;
 +  pio.piod_len = len;
 +
 +  if (ptrace (PT_IO, pid, &pio, 0) == -1)
-+    return 0;
++    perror_with_name (("ptrace"));
 +
 +  return pio.piod_len;
 +}
 +
++/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
++   to debugger memory starting at MYADDR.  */
++
++int
++netbsd_process_target::read_auxv (CORE_ADDR offset,
++				  unsigned char *myaddr, unsigned int len)
++{
++  pid_t pid = pid_of (current_thread);
++
++  return netbsd_read_auxv (pid, (void *) (intptr_t) offset, myaddr, len);
++}
++
 +bool
 +netbsd_process_target::supports_z_point_type (char z_type)
 +{
 +  switch (z_type)
 +    {
 +    case Z_PACKET_SW_BP:
-+#if 0
++      return true;
 +    case Z_PACKET_HW_BP:
 +    case Z_PACKET_WRITE_WP:
 +    case Z_PACKET_READ_WP:
 +    case Z_PACKET_ACCESS_WP:
-+#endif
-+      return true;
 +    default:
-+      return false;
++      return false; /* Not supported.  */
 +    }
 +}
 +
@@ -866,10 +751,10 @@ $NetBSD$
 +netbsd_process_target::stopped_by_sw_breakpoint ()
 +{
 +  ptrace_siginfo_t psi;
-+  pid_t pid = pid_of (current_thread);
++  pid_t pid = current_process ()->pid;
 +
-+  if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof(psi)) == -1)
-+    return -1; // XXX
++  if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
++    perror_with_name (("ptrace"));
 +
 +  return psi.psi_siginfo.si_signo == SIGTRAP &&
 +	 psi.psi_siginfo.si_code == TRAP_BRKPT;
@@ -884,44 +769,39 @@ $NetBSD$
 +  return true;
 +}
 +
-+int
-+netbsd_process_target::qxfer_siginfo (const char *annex, unsigned char *readbuf,
-+		     unsigned const char *writebuf, CORE_ADDR offset, int len)
-+{
-+  if (current_thread == NULL)
-+    return -1;
++/* Implement the supports_qxfer_siginfo target_ops method.  */
 +
-+  pid_t pid = pid_of (current_thread);
++bool
++netbsd_process_target::supports_qxfer_siginfo ()
++{
++  return true;
++}
 +
-+  if (offset >= sizeof (siginfo))
-+    return -1;
++/* Implement the qxfer_siginfo target_ops method.  */
 +
-+  struct ptrace_siginfo psi;
-+  if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof(psi)) != 0)
++int
++netbsd_process_target::qxfer_siginfo (const char *annex, unsigned char *readbuf,
++				      unsigned const char *writebuf,
++				      CORE_ADDR offset, int len)
++{
++  if (current_thread == nullptr)
 +    return -1;
 +
-+  if (offset + len > sizeof (siginfo))
-+    len = sizeof (siginfo) - offset;
-+
-+  if (readbuf != NULL)
-+    memcpy (readbuf, (char *)&psi.psi_siginfo + offset, len);
-+  else
-+    {
-+      memcpy ((char *)&psi.psi_siginfo + offset, writebuf, len);
++  pid_t pid = current_process ()->pid;
 +
-+      if (ptrace (PT_SET_SIGINFO, pid, &psi, sizeof(psi)) != 0)
-+	return -1;
-+    }
-+
-+  return len;
++  return netbsd_nat::qxfer_siginfo(pid, annex, readbuf, writebuf, offset, len);
 +}
 +
++/* Implement the supports_non_stop target_ops method.  */
++
 +bool
 +netbsd_process_target::supports_non_stop ()
 +{
 +  return false;
 +}
 +
++/* Implement the supports_multi_process target_ops method.  */
++
 +bool
 +netbsd_process_target::supports_multi_process ()
 +{
@@ -933,7 +813,7 @@ $NetBSD$
 +bool
 +netbsd_process_target::supports_fork_events ()
 +{
-+  return true;
++  return false;
 +}
 +
 +/* Check if vfork events are supported.  */
@@ -941,7 +821,7 @@ $NetBSD$
 +bool
 +netbsd_process_target::supports_vfork_events ()
 +{
-+  return true;
++  return false;
 +}
 +
 +/* Check if exec events are supported.  */
@@ -952,6 +832,8 @@ $NetBSD$
 +  return true;
 +}
 +
++/* Implement the supports_disable_randomization target_ops method.  */
++
 +bool
 +netbsd_process_target::supports_disable_randomization ()
 +{
@@ -960,57 +842,34 @@ $NetBSD$
 +
 +/* Extract &phdr and num_phdr in the inferior.  Return 0 on success.  */
 +
-+static int
-+get_phdr_phnum_from_proc_auxv (const int pid, const int is_elf64,
-+			       CORE_ADDR *phdr_memaddr, int *num_phdr)
++template <typename T>
++int get_phdr_phnum_from_proc_auxv (const pid_t pid,
++				   CORE_ADDR *phdr_memaddr, int *num_phdr)
 +{
-+  const int auxv_size = is_elf64
-+    ? sizeof (Aux64Info) : sizeof (Aux32Info);
-+  char *buf;
-+  const size_t auxv_buf_size = 100 * sizeof (Aux64Info);
++  typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
++				    Aux64Info, Aux32Info>::type auxv_type;
++  const size_t auxv_size = sizeof (auxv_type);
++  const size_t auxv_buf_size = 128 * sizeof (auxv_type);
 +
-+  char *auxv_buf = (char *)xmalloc (auxv_buf_size);
++  char *auxv_buf = (char *) xmalloc (auxv_buf_size);
 +
-+  struct ptrace_io_desc pio;
-+  pio.piod_op = PIOD_READ_AUXV;
-+  pio.piod_offs = 0;
-+  pio.piod_addr = auxv_buf;
-+  pio.piod_len = auxv_buf_size;
-+
-+  ptrace (PT_IO, pid, &pio, 0);
++  netbsd_read_auxv (pid, nullptr, auxv_buf, auxv_buf_size);
 +
 +  *phdr_memaddr = 0;
 +  *num_phdr = 0;
 +
-+  for (buf = auxv_buf; buf < (auxv_buf + auxv_buf_size); buf += auxv_size)
++  for (char *buf = auxv_buf; buf < (auxv_buf + auxv_buf_size); buf += auxv_size)
 +    {
-+      if (is_elf64)
-+	{
-+	  Aux64Info *const aux = (Aux64Info *) buf;
++      auxv_type *const aux = (auxv_type *) buf;
 +
-+	  switch (aux->a_type)
-+	    {
-+	    case AT_PHDR:
-+	      *phdr_memaddr = aux->a_v;
-+	      break;
-+	    case AT_PHNUM:
-+	      *num_phdr = aux->a_v;
-+	      break;
-+	    }
-+	}
-+      else
++      switch (aux->a_type)
 +	{
-+	  Aux32Info *const aux = (Aux32Info *) buf;
-+
-+	  switch (aux->a_type)
-+	    {
-+	    case AT_PHDR:
-+	      *phdr_memaddr = aux->a_v;
-+	      break;
-+	    case AT_PHNUM:
-+	      *num_phdr = aux->a_v;
-+	      break;
-+	    }
++	case AT_PHDR:
++	  *phdr_memaddr = aux->a_v;
++	  break;
++	case AT_PHNUM:
++	  *num_phdr = aux->a_v;
++	  break;
 +	}
 +
 +      if (*phdr_memaddr != 0 && *num_phdr != 0)
@@ -1032,41 +891,35 @@ $NetBSD$
 +
 +/* Return &_DYNAMIC (via PT_DYNAMIC) in the inferior, or 0 if not present.  */
 +
++template <typename T>
 +static CORE_ADDR
-+get_dynamic (netbsd_process_target *target, const int pid, const int is_elf64)
++get_dynamic (netbsd_process_target *target, const pid_t pid)
 +{
-+  CORE_ADDR phdr_memaddr, relocation;
-+  int num_phdr, i;
-+  unsigned char *phdr_buf;
-+  const int phdr_size = is_elf64 ? sizeof (Elf64_Phdr) : sizeof (Elf32_Phdr);
++  typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
++				    Elf64_Phdr, Elf32_Phdr>::type phdr_type;
++  const int phdr_size = sizeof (phdr_type);
 +
-+  if (get_phdr_phnum_from_proc_auxv (pid, is_elf64, &phdr_memaddr, &num_phdr))
++  CORE_ADDR phdr_memaddr;
++  int num_phdr;
++  if (get_phdr_phnum_from_proc_auxv<T> (pid, &phdr_memaddr, &num_phdr))
 +    return 0;
 +
-+  gdb_assert (num_phdr < 100);  /* Basic sanity check.  */
-+  phdr_buf = (unsigned char *) alloca (num_phdr * phdr_size);
++  std::vector<unsigned char> phdr_buf;
++  phdr_buf.resize (num_phdr * phdr_size);
 +
-+  if ((*target).read_memory (phdr_memaddr, phdr_buf, num_phdr * phdr_size))
++  if ((*target).read_memory (phdr_memaddr, phdr_buf.data (), phdr_buf.size ()))
 +    return 0;
 +
 +  /* Compute relocation: it is expected to be 0 for "regular" executables,
 +     non-zero for PIE ones.  */
-+  relocation = -1;
-+  for (i = 0; relocation == -1 && i < num_phdr; i++)
-+    if (is_elf64)
-+      {
-+	Elf64_Phdr *const p = (Elf64_Phdr *) (phdr_buf + i * phdr_size);
-+
-+	if (p->p_type == PT_PHDR)
-+	  relocation = phdr_memaddr - p->p_vaddr;
-+      }
-+    else
-+      {
-+	Elf32_Phdr *const p = (Elf32_Phdr *) (phdr_buf + i * phdr_size);
++  CORE_ADDR relocation = -1;
++  for (int i = 0; relocation == -1 && i < num_phdr; i++)
++    {
++      phdr_type *const p = (phdr_type *) (phdr_buf.data() + i * phdr_size);
 +
-+	if (p->p_type == PT_PHDR)
-+	  relocation = phdr_memaddr - p->p_vaddr;
-+      }
++      if (p->p_type == PT_PHDR)
++	relocation = phdr_memaddr - p->p_vaddr;
++    }
 +
 +  if (relocation == -1)
 +    {
@@ -1083,22 +936,12 @@ $NetBSD$
 +      return 0;
 +    }
 +
-+  for (i = 0; i < num_phdr; i++)
++  for (int i = 0; i < num_phdr; i++)
 +    {
-+      if (is_elf64)
-+	{
-+	  Elf64_Phdr *const p = (Elf64_Phdr *) (phdr_buf + i * phdr_size);
-+
-+	  if (p->p_type == PT_DYNAMIC)
-+	    return p->p_vaddr + relocation;
-+	}
-+      else
-+	{
-+	  Elf32_Phdr *const p = (Elf32_Phdr *) (phdr_buf + i * phdr_size);
++      phdr_type *const p = (phdr_type *) (phdr_buf.data () + i * phdr_size);
 +
-+	  if (p->p_type == PT_DYNAMIC)
-+	    return p->p_vaddr + relocation;
-+	}
++      if (p->p_type == PT_DYNAMIC)
++	return p->p_vaddr + relocation;
 +    }
 +
 +  return 0;
@@ -1109,96 +952,46 @@ $NetBSD$
 +   We look for DT_MIPS_RLD_MAP first.  MIPS executables use this instead of
 +   DT_DEBUG, although they sometimes contain an unused DT_DEBUG entry too.  */
 +
++template <typename T>
 +static CORE_ADDR
-+get_r_debug (netbsd_process_target *target, const int pid, const int is_elf64)
++get_r_debug (netbsd_process_target *target, const int pid)
 +{
-+  CORE_ADDR dynamic_memaddr;
-+  const int dyn_size = is_elf64 ? sizeof (Elf64_Dyn) : sizeof (Elf32_Dyn);
-+  unsigned char buf[sizeof (Elf64_Dyn)];  /* The larger of the two.  */
++  typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
++				    Elf64_Dyn, Elf32_Dyn>::type dyn_type;
++  const int dyn_size = sizeof (dyn_type);
++  unsigned char buf[sizeof (dyn_type)];  /* The larger of the two.  */
 +  CORE_ADDR map = -1;
 +
-+  dynamic_memaddr = get_dynamic (target, pid, is_elf64);
++  CORE_ADDR dynamic_memaddr = get_dynamic<T> (target, pid);
 +  if (dynamic_memaddr == 0)
 +    return map;
 +
 +  while ((*target).read_memory (dynamic_memaddr, buf, dyn_size) == 0)
 +    {
-+      if (is_elf64)
-+	{
-+	  Elf64_Dyn *const dyn = (Elf64_Dyn *) buf;
-+#if defined DT_MIPS_RLD_MAP || defined DT_MIPS_RLD_MAP_REL
-+	  union
-+	    {
-+	      Elf64_Xword map;
-+	      unsigned char buf[sizeof (Elf64_Xword)];
-+	    }
-+	  rld_map;
-+#endif
-+#ifdef DT_MIPS_RLD_MAP
-+	  if (dyn->d_tag == DT_MIPS_RLD_MAP)
-+	    {
-+	      if (read_memory (dyn->d_un.d_val,
-+				     rld_map.buf, sizeof (rld_map.buf)) == 0)
-+		return rld_map.map;
-+	      else
-+		break;
-+	    }
-+#endif  /* DT_MIPS_RLD_MAP */
-+#ifdef DT_MIPS_RLD_MAP_REL
-+	  if (dyn->d_tag == DT_MIPS_RLD_MAP_REL)
-+	    {
-+	      if (read_memory (dyn->d_un.d_val + dynamic_memaddr,
-+				     rld_map.buf, sizeof (rld_map.buf)) == 0)
-+		return rld_map.map;
-+	      else
-+		break;
-+	    }
-+#endif  /* DT_MIPS_RLD_MAP_REL */
-+
-+	  if (dyn->d_tag == DT_DEBUG && map == -1)
-+	    map = dyn->d_un.d_val;
++      dyn_type *const dyn = (dyn_type *) buf;
++#if defined DT_MIPS_RLD_MAP
++      union
++      {
++	T map;
++	unsigned char buf[sizeof (T)];
++      }
++      rld_map;
 +
-+	  if (dyn->d_tag == DT_NULL)
++      if (dyn->d_tag == DT_MIPS_RLD_MAP)
++	{
++	  if (read_memory (dyn->d_un.d_val,
++			   rld_map.buf, sizeof (rld_map.buf)) == 0)
++	    return rld_map.map;
++	  else
 +	    break;
 +	}
-+      else
-+	{
-+	  Elf32_Dyn *const dyn = (Elf32_Dyn *) buf;
-+#if defined DT_MIPS_RLD_MAP || defined DT_MIPS_RLD_MAP_REL
-+	  union
-+	    {
-+	      Elf32_Word map;
-+	      unsigned char buf[sizeof (Elf32_Word)];
-+	    }
-+	  rld_map;
-+#endif
-+#ifdef DT_MIPS_RLD_MAP
-+	  if (dyn->d_tag == DT_MIPS_RLD_MAP)
-+	    {
-+	      if (read_memory (dyn->d_un.d_val,
-+			       rld_map.buf, sizeof (rld_map.buf)) == 0)
-+		return rld_map.map;
-+	      else
-+		break;
-+	    }
 +#endif  /* DT_MIPS_RLD_MAP */
-+#ifdef DT_MIPS_RLD_MAP_REL
-+	  if (dyn->d_tag == DT_MIPS_RLD_MAP_REL)
-+	    {
-+	      if (read_memory (dyn->d_un.d_val + dynamic_memaddr,
-+			       rld_map.buf, sizeof (rld_map.buf)) == 0)
-+		return rld_map.map;
-+	      else
-+		break;
-+	    }
-+#endif  /* DT_MIPS_RLD_MAP_REL */
 +
-+	  if (dyn->d_tag == DT_DEBUG && map == -1)
-+	    map = dyn->d_un.d_val;
++      if (dyn->d_tag == DT_DEBUG && map == -1)
++	map = dyn->d_un.d_val;
 +
-+	  if (dyn->d_tag == DT_NULL)
-+	    break;
-+	}
++      if (dyn->d_tag == DT_NULL)
++	break;
 +
 +      dynamic_memaddr += dyn_size;
 +    }
@@ -1237,7 +1030,17 @@ $NetBSD$
 +  return ret;
 +}
 +
-+struct link_map_offsets
++/* Construct qXfer:libraries-svr4:read reply.  */
++
++template <typename T>
++int
++netbsd_qxfer_libraries_svr4 (netbsd_process_target *target,
++			     const pid_t pid, const char *annex,
++			     unsigned char *readbuf,
++			     unsigned const char *writebuf,
++			     CORE_ADDR offset, int len)
++{
++  struct link_map_offsets
 +  {
 +    /* Offset and size of r_debug.r_version.  */
 +    int r_version_offset;
@@ -1261,67 +1064,6 @@ $NetBSD$
 +    int l_prev_offset;
 +  };
 +
-+/* Return non-zero if HEADER is a 64-bit ELF file.  */
-+
-+static int
-+elf_64_header_p (const Elf64_Ehdr *header, unsigned int *machine)
-+{
-+  if (header->e_ident[EI_MAG0] == ELFMAG0
-+      && header->e_ident[EI_MAG1] == ELFMAG1
-+      && header->e_ident[EI_MAG2] == ELFMAG2
-+      && header->e_ident[EI_MAG3] == ELFMAG3)
-+    {
-+      *machine = header->e_machine;
-+      return header->e_ident[EI_CLASS] == ELFCLASS64;
-+
-+    }
-+  *machine = EM_NONE;
-+  return -1;
-+}
-+
-+/* Return non-zero if FILE is a 64-bit ELF file,
-+   zero if the file is not a 64-bit ELF file,
-+   and -1 if the file is not accessible or doesn't exist.  */
-+
-+static int
-+elf_64_file_p (const char *file, unsigned int *machine)
-+{
-+  Elf64_Ehdr header;
-+  int fd;
-+
-+  fd = open (file, O_RDONLY);
-+  if (fd < 0)
-+    return -1;
-+
-+  if (read (fd, &header, sizeof (header)) != sizeof (header))
-+    {
-+      close (fd);
-+      return 0;
-+    }
-+  close (fd);
-+
-+  int is64 = elf_64_header_p (&header, machine);
-+
-+  return is64;
-+}
-+
-+bool
-+netbsd_process_target::supports_qxfer_libraries_svr4 ()
-+{
-+  return true;
-+}
-+
-+/* Construct qXfer:libraries-svr4:read reply.  */
-+
-+int
-+netbsd_process_target::qxfer_libraries_svr4 (const char *annex,
-+					     unsigned char *readbuf,
-+					     unsigned const char *writebuf,
-+					     CORE_ADDR offset, int len)
-+{
-+  struct process_info_private *const priv = current_process ()->priv;
-+  int pid, is_elf64;
-+
 +  static const struct link_map_offsets lmo_32bit_offsets =
 +    {
 +      0,     /* r_version offset. */
@@ -1343,34 +1085,24 @@ $NetBSD$
 +      24,    /* l_next offset in link_map.  */
 +      32     /* l_prev offset in link_map.  */
 +    };
-+  const struct link_map_offsets *lmo;
-+  unsigned int machine;
-+  int ptr_size;
++
 +  CORE_ADDR lm_addr = 0, lm_prev = 0;
 +  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
 +  int header_done = 0;
 +
-+  if (writebuf != NULL)
-+    return -2;
-+  if (readbuf == NULL)
-+    return -1;
-+
-+  pid = pid_of (current_thread);
-+  is_elf64 = elf_64_file_p (pid_to_exec_file(pid), &machine);
-+  lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
-+  ptr_size = is_elf64 ? 8 : 4;
++  const struct link_map_offsets *lmo
++    = (sizeof (T) == sizeof (int64_t))
++    ? &lmo_64bit_offsets : &lmo_32bit_offsets;
++  int ptr_size = sizeof (T);
 +
 +  while (annex[0] != '\0')
 +    {
-+      const char *sep;
-+      CORE_ADDR *addrp;
-+      int name_len;
-+
-+      sep = strchr (annex, '=');
-+      if (sep == NULL)
++      const char *sep = strchr (annex, '=');
++      if (sep == nullptr)
 +	break;
 +
-+      name_len = sep - annex;
++      int name_len = sep - annex;
++      CORE_ADDR *addrp;
 +      if (name_len == 5 && startswith (annex, "start"))
 +	addrp = &lm_addr;
 +      else if (name_len == 4 && startswith (annex, "prev"))
@@ -1378,7 +1110,7 @@ $NetBSD$
 +      else
 +	{
 +	  annex = strchr (sep, ';');
-+	  if (annex == NULL)
++	  if (annex == nullptr)
 +	    break;
 +	  annex++;
 +	  continue;
@@ -1389,31 +1121,21 @@ $NetBSD$
 +
 +  if (lm_addr == 0)
 +    {
-+      int r_version = 0;
-+
-+      if (priv->r_debug == 0)
-+	priv->r_debug = get_r_debug (this, pid, is_elf64);
++      CORE_ADDR r_debug = get_r_debug<T> (target, pid);
 +
 +      /* We failed to find DT_DEBUG.  Such situation will not change
 +	 for this inferior - do not retry it.  Report it to GDB as
 +	 E01, see for the reasons at the GDB solib-svr4.c side.  */
-+      if (priv->r_debug == (CORE_ADDR) -1)
++      if (r_debug == (CORE_ADDR) -1)
 +	return -1;
 +
-+      if (priv->r_debug != 0)
++      if (r_debug != 0)
 +	{
-+	  if (read_memory (priv->r_debug + lmo->r_version_offset,
-+			   (unsigned char *) &r_version,
-+			   sizeof (r_version)) != 0
-+	      || r_version != 1)
-+	    {
-+	      warning ("unexpected r_debug version %d", r_version);
-+	    }
-+	  else if (read_one_ptr (this, priv->r_debug + lmo->r_map_offset,
-+				 &lm_addr, ptr_size) != 0)
++	  if (read_one_ptr (target, r_debug + lmo->r_map_offset,
++			    &lm_addr, ptr_size) != 0)
 +	    {
 +	      warning ("unable to read r_map from 0x%lx",
-+		       (long) priv->r_debug + lmo->r_map_offset);
++		       (long) r_debug + lmo->r_map_offset);
 +	    }
 +	}
 +    }
@@ -1421,19 +1143,17 @@ $NetBSD$
 +  std::string document = "<library-list-svr4 version=\"1.0\"";
 +
 +  while (lm_addr
-+	 && read_one_ptr (this, lm_addr + lmo->l_name_offset,
++	 && read_one_ptr (target, lm_addr + lmo->l_name_offset,
 +			  &l_name, ptr_size) == 0
-+	 && read_one_ptr (this, lm_addr + lmo->l_addr_offset,
++	 && read_one_ptr (target, lm_addr + lmo->l_addr_offset,
 +			  &l_addr, ptr_size) == 0
-+	 && read_one_ptr (this, lm_addr + lmo->l_ld_offset,
++	 && read_one_ptr (target, lm_addr + lmo->l_ld_offset,
 +			  &l_ld, ptr_size) == 0
-+	 && read_one_ptr (this, lm_addr + lmo->l_prev_offset,
++	 && read_one_ptr (target, lm_addr + lmo->l_prev_offset,
 +			  &l_prev, ptr_size) == 0
-+	 && read_one_ptr (this, lm_addr + lmo->l_next_offset,
++	 && read_one_ptr (target, lm_addr + lmo->l_next_offset,
 +			  &l_next, ptr_size) == 0)
 +    {
-+      unsigned char libname[PATH_MAX];
-+
 +      if (lm_prev != l_prev)
 +	{
 +	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
@@ -1448,13 +1168,16 @@ $NetBSD$
 +	 executable does not have PT_DYNAMIC present and this function already
 +	 exited above due to failed get_r_debug.  */
 +      if (lm_prev == 0)
-+	string_appendf (document, " main-lm=\"0x%lx\"", (unsigned long) lm_addr);
++	string_appendf (document, " main-lm=\"0x%lx\"",
++			(unsigned long) lm_addr);
 +      else
 +	{
++	  unsigned char libname[PATH_MAX];
++
 +	  /* Not checking for error because reading may stop before
 +	     we've got PATH_MAX worth of characters.  */
 +	  libname[0] = '\0';
-+	  read_memory (l_name, libname, sizeof (libname) - 1);
++	  (*target).read_memory (l_name, libname, sizeof (libname) - 1);
 +	  libname[sizeof (libname) - 1] = '\0';
 +	  if (libname[0] != '\0')
 +	    {
@@ -1499,13 +1222,74 @@ $NetBSD$
 +  return len;
 +}
 +
++/* Return true if FILE is a 64-bit ELF file,
++   false if the file is not a 64-bit ELF file,
++   and error if the file is not accessible or doesn't exist.  */
++
++static bool
++elf_64_file_p (const char *file)
++{
++  int fd = gdb::handle_eintr (::open, file, O_RDONLY);
++  if (fd < 0)
++    perror_with_name (("open"));
++
++  Elf64_Ehdr header;
++  ssize_t ret = gdb::handle_eintr (::read, fd, &header, sizeof (header));
++  if (ret == -1)
++    perror_with_name (("read"));
++  gdb::handle_eintr (::close, fd);
++  if (ret != sizeof (header))
++    error ("Cannot read ELF file header: %s", file);
++
++  if (header.e_ident[EI_MAG0] != ELFMAG0
++      || header.e_ident[EI_MAG1] != ELFMAG1
++      || header.e_ident[EI_MAG2] != ELFMAG2
++      || header.e_ident[EI_MAG3] != ELFMAG3)
++    error ("Unrecognized ELF file header: %s", file);
++
++  return header.e_ident[EI_CLASS] == ELFCLASS64;
++}
++
++/* Construct qXfer:libraries-svr4:read reply.  */
++
++int
++netbsd_process_target::qxfer_libraries_svr4 (const char *annex,
++					     unsigned char *readbuf,
++					     unsigned const char *writebuf,
++					     CORE_ADDR offset, int len)
++{
++  if (writebuf != nullptr)
++    return -2;
++  if (readbuf == nullptr)
++    return -1;
++
++  struct process_info *proc = current_process ();
++  pid_t pid = proc->pid;
++  bool is_elf64 = elf_64_file_p (netbsd_nat::pid_to_exec_file (pid));
++
++  if (is_elf64)
++    return netbsd_qxfer_libraries_svr4<int64_t> (this, pid, annex, readbuf,
++						 writebuf, offset, len);
++  else
++    return netbsd_qxfer_libraries_svr4<int32_t> (this, pid, annex, readbuf,
++						 writebuf, offset, len);
++}
++
++/* Implement the supports_qxfer_libraries_svr4 target_ops method.  */
++
++bool
++netbsd_process_target::supports_qxfer_libraries_svr4 ()
++{
++  return true;
++}
++
 +/* Return the name of a file that can be opened to get the symbols for
 +   the child process identified by PID.  */
 +
 +char *
 +netbsd_process_target::pid_to_exec_file (pid_t pid)
 +{
-+  return netbsd_pid_to_exec_file(pid);
++  return netbsd_nat::pid_to_exec_file (pid);
 +}
 +
 +/* Implementation of the target_ops method "supports_pid_to_exec_file".  */
@@ -1532,59 +1316,29 @@ $NetBSD$
 +
 +  *size = PTRACE_BREAKPOINT_SIZE;
 +
-+  memcpy(brkpt, PTRACE_BREAKPOINT, PTRACE_BREAKPOINT_SIZE);
++  memcpy (brkpt, PTRACE_BREAKPOINT, PTRACE_BREAKPOINT_SIZE);
 +
 +  return brkpt;
 +}
 +
++/* Implement the thread_name target_ops method.  */
++
 +const char *
 +netbsd_process_target::thread_name (ptid_t ptid)
 +{
-+  struct kinfo_lwp *kl;
-+  pid_t pid = ptid.pid ();
-+  lwpid_t lwp = ptid.lwp ();
-+  static char buf[KI_LNAMELEN];
-+  int mib[5];
-+  size_t i, nlwps;
-+  size_t size;
-+
-+  mib[0] = CTL_KERN;
-+  mib[1] = KERN_LWP;
-+  mib[2] = pid;
-+  mib[3] = sizeof (struct kinfo_lwp);
-+  mib[4] = 0;
-+
-+  if (sysctl (mib, 5, NULL, &size, NULL, 0) == -1 || size == 0)
-+    perror_with_name (("sysctl"));
-+
-+  mib[4] = size / sizeof(size_t);
-+
-+  kl = (struct kinfo_lwp *) xmalloc (size);
-+  if (kl == NULL)
-+    perror_with_name (("malloc"));
-+
-+  if (sysctl (mib, 5, kl, &size, NULL, 0) == -1 || size == 0)
-+    perror_with_name (("sysctl"));
-+
-+  nlwps = size / sizeof (struct kinfo_lwp);
-+  buf[0] = '\0';
-+  for (i = 0; i < nlwps; i++) {
-+    if (kl[i].l_lid == lwp) {
-+      xsnprintf (buf, sizeof buf, "%s", kl[i].l_name);
-+      break;
-+    }
-+  }
-+  xfree (kl);
-+
-+  return buf;
++  return netbsd_nat::thread_name (ptid);
 +}
 +
++/* Implement the supports_catch_syscall target_ops method.  */
++
 +bool
 +netbsd_process_target::supports_catch_syscall ()
 +{
 +  return true;
 +}
 +
++/* Implement the supports_read_auxv target_ops method.  */
++
 +bool
 +netbsd_process_target::supports_read_auxv ()
 +{
diff --git a/gdb-netbsd/patches/patch-gdbserver_netbsd-low.h b/gdb-netbsd/patches/patch-gdbserver_netbsd-low.h
index 288c775ba9..452ff3478e 100644
--- a/gdb-netbsd/patches/patch-gdbserver_netbsd-low.h
+++ b/gdb-netbsd/patches/patch-gdbserver_netbsd-low.h
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- gdbserver/netbsd-low.h.orig	2020-08-27 02:43:00.927090317 +0000
+--- gdbserver/netbsd-low.h.orig	2020-09-02 16:10:13.482596165 +0000
 +++ gdbserver/netbsd-low.h
-@@ -0,0 +1,153 @@
+@@ -0,0 +1,157 @@
 +/* Copyright (C) 2020 Free Software Foundation, Inc.
 +
 +   This file is part of GDB.
@@ -67,6 +67,8 @@ $NetBSD$
 +  int create_inferior (const char *program,
 +		       const std::vector<char *> &program_args) override;
 +
++  void post_create_inferior () override;
++
 +  int attach (unsigned long pid) override;
 +
 +  int kill (process_info *proc) override;
@@ -97,7 +99,7 @@ $NetBSD$
 +  void request_interrupt () override;
 +
 +  bool supports_read_auxv () override;
-+  
++
 +  int read_auxv (CORE_ADDR offset, unsigned char *myaddr,
 +		 unsigned int len) override;
 +
@@ -115,6 +117,8 @@ $NetBSD$
 +
 +  bool stopped_by_sw_breakpoint () override;
 +
++  bool supports_qxfer_siginfo () override;
++
 +  int qxfer_siginfo (const char *annex, unsigned char *readbuf,
 +		     unsigned const char *writebuf, CORE_ADDR offset,
 +		     int len) override;
@@ -134,12 +138,12 @@ $NetBSD$
 +  bool supports_disable_randomization () override;
 +
 +  bool supports_qxfer_libraries_svr4 () override;
-+  
++
 +  int qxfer_libraries_svr4 (const char*, unsigned char*, const unsigned char*,
 +			    CORE_ADDR, int) override;
 +
 +  bool supports_pid_to_exec_file () override;
-+  
++
 +  char *pid_to_exec_file (int pid) override;
 +
 +  const char *thread_name (ptid_t thread) override;
diff --git a/gdb-netbsd/patches/patch-gdbserver_netbsd-x86__64-low.cc b/gdb-netbsd/patches/patch-gdbserver_netbsd-x86__64-low.cc
index af7d6ce26e..382922aae7 100644
--- a/gdb-netbsd/patches/patch-gdbserver_netbsd-x86__64-low.cc
+++ b/gdb-netbsd/patches/patch-gdbserver_netbsd-x86__64-low.cc
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- gdbserver/netbsd-x86_64-low.cc.orig	2020-08-27 02:43:00.927238751 +0000
+--- gdbserver/netbsd-x86_64-low.cc.orig	2020-09-02 16:10:13.482761789 +0000
 +++ gdbserver/netbsd-x86_64-low.cc
 @@ -0,0 +1,250 @@
 +/* Copyright (C) 2020 Free Software Foundation, Inc.
diff --git a/gdb-netbsd/patches/patch-gdbsupport_eintr.h b/gdb-netbsd/patches/patch-gdbsupport_eintr.h
new file mode 100644
index 0000000000..4d154cc695
--- /dev/null
+++ b/gdb-netbsd/patches/patch-gdbsupport_eintr.h
@@ -0,0 +1,46 @@
+$NetBSD$
+
+--- gdbsupport/eintr.h.orig	2020-09-02 16:10:13.482874765 +0000
++++ gdbsupport/eintr.h
+@@ -0,0 +1,41 @@
++/* Utility for handling interrupted syscalls by signals.
++
++   Copyright (C) 2020 Free Software Foundation, Inc.
++
++   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 GDBSUPPORT_EINTR_H
++#define GDBSUPPORT_EINTR_H
++
++#include <cerrno>
++
++namespace gdb
++{
++template <typename Fun, typename... Args>
++inline decltype (auto) handle_eintr (const Fun &F, const Args &... A)
++{
++  decltype (F (A...)) ret;
++  do
++    {
++      errno = 0;
++      ret = F (A...);
++    }
++  while (ret == -1 && errno == EINTR);
++  return ret;
++}
++}
++
++#endif /* GDBSUPPORT_EINTR_H */


Home | Main Index | Thread Index | Old Index