Index | Thread | Search

From:
Kurt Miller <kurt@intricatesoftware.com>
Subject:
devel/gdb: updated p1 diff with addtional bug fix
To:
jca@wxcvbn.org, pascal@stumpf.co, ports@openbsd.org, tech@openbsd.org
Date:
Fri, 12 Dec 2025 16:09:36 +0000

Download raw body.

Thread
This is a new version of gdb bug fixes. It now includes a fix for
attaching to running processes to allow ^C to interrupt and bring
the debugger back to the prompt. I also removed the ifdef guards
on PT_PTS_NAMELEN to ensure p1 is built against base with that
define.

The issue with ^C on attached processes is that gdb clears the
global inferior_ptid and installs the pass_signal handler for
SIGINT on its way to calling waitpid. When SIGINT is received
pass_signal was calling kill(0, SIGINT) which sends the signal
to the process group of gdb. However, since we attached to an
existing process in a different process group, we essentially
sent SIGINT back to gdb, causing us to be suck in a SIGINT
storm. After trying to understand how to fix this the right
way, I eventually gave up and looked at what FreeBSD does. They
have a hack for this that works for us too.

In short this diff does the following:
* Uses ptrace PT_GET_THREAD_* for both setting thread names and
detecting if threads are still alive. The thread_alive detection
fixes 'info threads' of processes whose threads exit while
debugging.
* Fixes SIGINT storm using patch from FreeBSD to direct the SIGINT
to the current inferior process instead of gdb's process group.
This allows ^C to bring us back to the gdb prompt on attached
processes.

okay?

Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/gdb/Makefile,v
diff -u -p -u -r1.98 Makefile
--- Makefile	4 Dec 2025 18:28:32 -0000	1.98
+++ Makefile	12 Dec 2025 15:36:29 -0000
@@ -2,7 +2,7 @@ COMMENT=	GNU debugger
 CATEGORIES=	devel
 
 DISTNAME=	gdb-16.3
-REVISION=	0
+REVISION=	1
 
 HOMEPAGE=	https://www.gnu.org/software/gdb/
 
Index: patches/patch-gdb_inflow_c
===================================================================
RCS file: patches/patch-gdb_inflow_c
diff -N patches/patch-gdb_inflow_c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-gdb_inflow_c	12 Dec 2025 15:36:29 -0000
@@ -0,0 +1,17 @@
+Pass SIGINT to attached inferior
+
+Index: gdb/inflow.c
+--- gdb/inflow.c.orig
++++ gdb/inflow.c
+@@ -872,7 +872,10 @@ static void
+ pass_signal (int signo)
+ {
+ #ifndef _WIN32
+-  kill (inferior_ptid.pid (), SIGINT);
++  if (inferior_ptid.pid ())
++    kill (inferior_ptid.pid (), SIGINT);
++  else
++    kill (current_inferior ()->pid, SIGINT);
+ #endif
+ }
+ 
Index: patches/patch-gdb_obsd-nat_c
===================================================================
RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_obsd-nat_c,v
diff -u -p -u -r1.1 patch-gdb_obsd-nat_c
--- patches/patch-gdb_obsd-nat_c	4 Dec 2025 18:28:32 -0000	1.1
+++ patches/patch-gdb_obsd-nat_c	12 Dec 2025 15:36:29 -0000
@@ -1,15 +1,9 @@
-Add support for thread_name.
+Add support for thread_name and thread_alive using ptrace.
 
 Index: gdb/obsd-nat.c
 --- gdb/obsd-nat.c.orig
 +++ gdb/obsd-nat.c
-@@ -23,11 +23,13 @@
- 
- #include <sys/types.h>
- #include <sys/ptrace.h>
-+#include <sys/sysctl.h>
- #include "gdbsupport/gdb_wait.h"
- 
+@@ -28,6 +28,7 @@
  #include "inf-ptrace.h"
  #include "obsd-nat.h"
  #include "gdbsupport/eintr.h"
@@ -17,48 +11,129 @@ Index: gdb/obsd-nat.c
  
  /* OpenBSD 5.2 and later include rthreads which uses a thread model
     that maps userland threads directly onto kernel threads in a 1:1
-@@ -183,4 +185,69 @@ int
- obsd_nat_target::remove_fork_catchpoint (int pid)
- {
-   return 0;
-+}
-+
+@@ -42,34 +43,78 @@ obsd_nat_target::pid_to_str (ptid_t ptid)
+   return normal_pid_to_str (ptid);
+ }
+ 
+-void
+-obsd_nat_target::update_thread_list ()
 +/* Generic thread lister within a specified PID.  The CALLBACK
 +   parameters is a C++ function that is called for each detected thread.
 +   When the CALLBACK function returns true, the iteration is interrupted.
 +
-+   This function assumes internally that the queried process is stopped
-+   and the number of threads does not change between two sysctl () calls.  */
++   This function assumes internally that the queried process is stopped. */
 +
 +static bool
 +obsd_thread_lister (const pid_t pid,
-+		      gdb::function_view<bool (const struct kinfo_proc *)>
++		      gdb::function_view<bool (const struct ptrace_thread_state *)>
 +		      callback)
-+{
-+  int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
-+      pid, sizeof(struct kinfo_proc), 0};
-+  size_t size;
-+
-+  if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
-+    perror_with_name (("sysctl"));
-+
-+  mib[5] = size / sizeof (struct kinfo_proc);
-+
-+  gdb::unique_xmalloc_ptr<struct kinfo_proc[]> ki
-+    ((struct kinfo_proc *) xcalloc (mib[5], sizeof (struct kinfo_proc)));
-+
-+  if (sysctl (mib, ARRAY_SIZE (mib), ki.get (), &size, NULL, 0) == -1
-+      || size == 0)
-+    perror_with_name (("sysctl"));
-+
-+  for (size_t i = 0; i < size / sizeof (struct kinfo_proc); i++)
-+    {
-+      struct kinfo_proc *l = &ki[i];
-+      if (callback (l))
+ {
+-  pid_t pid = inferior_ptid.pid ();
+   struct ptrace_thread_state pts;
+ 
+-  prune_threads ();
+-
+   if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1)
+     perror_with_name (("ptrace"));
+ 
+   while (pts.pts_tid != -1)
+     {
+-      ptid_t ptid = ptid_t (pid, pts.pts_tid, 0);
+-
+-      if (!in_thread_list (this, ptid))
+-	{
+-	  if (inferior_ptid.lwp () == 0)
+-	    thread_change_ptid (this, inferior_ptid, ptid);
+-	  else
+-	    add_thread (this, ptid);
+-	}
+-
++      if (callback (&pts))
 +	return true;
-+    }
+       if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1)
+ 	perror_with_name (("ptrace"));
+     }
 +
 +  return false;
+ }
+ 
++/* Fuction to support executing callback for each alive thread */
++
++static void
++for_each_thread (pid_t pid, gdb::function_view<void (ptid_t)> callback)
++{
++  auto fn
++    = [=, &callback] (const struct ptrace_thread_state *pts)
++      {
++	ptid_t ptid = ptid_t (pid, pts->pts_tid, 0);
++	callback (ptid);
++	return false;
++      };
++
++  obsd_thread_lister (pid, fn);
++}
++
++/* Implement the "post_attach" target_ops method.  */
++
++static void
++obsd_add_threads (obsd_nat_target *target, pid_t pid)
++{
++  auto fn
++    = [&target] (ptid_t ptid)
++      {
++	if (!in_thread_list (target, ptid))
++	  {
++	    if (inferior_ptid.lwp () == 0)
++	      thread_change_ptid (target, inferior_ptid, ptid);
++	    else
++	      add_thread (target, ptid);
++	  }
++      };
++
++  for_each_thread (pid, fn);
++}
++
++void
++obsd_nat_target::update_thread_list ()
++{
++  pid_t pid = inferior_ptid.pid ();
++
++  prune_threads ();
++  obsd_add_threads (this, pid);
++}
++
+ /* Enable additional event reporting on a new or existing process.  */
+ 
+ static void
+@@ -143,6 +188,7 @@ void
+ obsd_nat_target::post_attach (int pid)
+ {
+   obsd_enable_proc_events (pid);
++  obsd_add_threads (this, pid);
+ }
+ 
+ /* Implement the virtual inf_ptrace_target::post_startup_inferior method.  */
+@@ -183,4 +229,48 @@ int
+ obsd_nat_target::remove_fork_catchpoint (int pid)
+ {
+   return 0;
++}
++
++/* See obsd-nat.h.  */
++
++bool
++obsd_nat_target::thread_alive (ptid_t ptid)
++{
++  pid_t pid = ptid.pid ();
++  ptid_t::lwp_type tid = ptid.lwp ();
++
++  auto fn
++    = [=] (const struct ptrace_thread_state *pts)
++      {
++	return pts->pts_tid == tid;
++      };
++
++  return obsd_thread_lister (pid, fn);
 +}
 +
 +/* See obsd-nat.h.  */
@@ -69,14 +144,14 @@ Index: gdb/obsd-nat.c
 +  pid_t pid = thr->ptid.pid ();
 +  ptid_t::lwp_type tid = thr->ptid.lwp ();
 +
-+  static char buf[KI_MAXCOMLEN] = {};
++  static char buf[PT_PTS_NAMELEN] = {};
 +
 +  auto fn
-+    = [=] (const struct kinfo_proc *ki)
++    = [=] (const struct ptrace_thread_state *pts)
 +      {
-+	if (ki->p_tid == tid)
++	if (pts->pts_tid == tid)
 +	  {
-+	    xsnprintf (buf, sizeof buf, "%s", ki->p_name);
++	    xsnprintf (buf, sizeof buf, "%s", pts->pts_name);
 +	    return true;
 +	  }
 +	return false;
Index: patches/patch-gdb_obsd-nat_h
===================================================================
RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_obsd-nat_h,v
diff -u -p -u -r1.1 patch-gdb_obsd-nat_h
--- patches/patch-gdb_obsd-nat_h	4 Dec 2025 18:28:32 -0000	1.1
+++ patches/patch-gdb_obsd-nat_h	12 Dec 2025 15:36:29 -0000
@@ -1,12 +1,13 @@
-Add support for thread_name.
+Add support for thread_name and thread_alive.
 
 Index: gdb/obsd-nat.h
 --- gdb/obsd-nat.h.orig
 +++ gdb/obsd-nat.h
-@@ -27,6 +27,7 @@ class obsd_nat_target : public inf_ptrace_target
+@@ -27,6 +27,8 @@ class obsd_nat_target : public inf_ptrace_target
    /* Override some methods to support threads.  */
    std::string pid_to_str (ptid_t) override;
    void update_thread_list () override;
++  bool thread_alive (ptid_t ptid) override;
 +  const char *thread_name (struct thread_info *thr) override;
    ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;