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

some support for debugging threads in gdb on kfreebsd



This is not yet complete or debugged, but it improves things.

The signals.c patch makes gdb not be confused by the signals that
LinuxThreads(sic) uses internally; you can even 'handle LTRESTART
nostop' if you prefer (you probably do so prefer).  This is a slightly
different version of a patch that I attached to bug #698200 in that it
gives these signals names that you can pass to 'handle' (the numbers
didn't work)

Even so, this doesn't make 'info threads' work.  That's what the 
inf-ptrace.c patch does.  Unfortunately, the main thread is listed twice
and I haven't found out how to avoid that yet.  Also, it makes me wonder
why PT_LWPINFO and friends are commented out in <sys/ptrace.h>; they
seem to work just fine.  Also, this may belong in amd64bsd-nat.c or some
other more system-specific file than inf-ptrace.c.

And this doesn't make the 'thread' command work, either.  For that to
work, it's necessary to use the TID (instead of the PID) in many (most?
all?) ptrace calls.  The middle patch, to amd64bsd-nat.c, does this
enough to make 'thread 2' and 'thread apply all bt' work.

The main problems I've observed so far are the dual-listing of the main
thread, and a repeatable crash when listing threads when not in the main
thread:

    (gdb) thread 2
    [Switching to thread 2 (process 15205)]
    #0  syscall () at ../ports/sysdeps/unix/bsd/bsd4.4/kfreebsd/x86_64/syscall.S:27
    27      ../ports/sysdeps/unix/bsd/bsd4.4/kfreebsd/x86_64/syscall.S: No such file or directory.
    (gdb) info threads

    Program received signal SIGSEGV, Segmentation fault.
    0x00000000004efdf1 in add_thread_object (tp=0x10720a0)
        at /store/src/gdb-7.4.1/gdb/python/py-inferior.c:247
    247       entry->next = inf_obj->threads;
    (top-gdb) 

I don't know what this is about yet, but it seems to mean that debugging
threads is likely to still be a minefield.

oh, and I just noticed another oddity, threads don't become known until
you 'info thread':
    (gdb) thread 2
    Thread ID 2 not known.
    (gdb) info thread
    [New process 19492]
    [New process 19492]
    [New process 19492]
      Id   Target Id         Frame 
      4    process 19492     __pthread_sigsuspend () at ../ports/sysdeps/unix/bsd/bsd4.4/kfreebsd/linuxthreads/pt-sigsuspend.S:24
      3    process 19492     0x0000000800b083e9 in poll () at ../sysdeps/unix/syscall-template.S:82
      2    process 19492     pthread_start_thread (arg=0x6041a0) at manager.c:260
    * 1    process 19492     __pthread_sigsuspend () at ../ports/sysdeps/unix/bsd/bsd4.4/kfreebsd/linuxthreads/pt-sigsuspend.S:24
    (gdb) thread 2
    [Switching to thread 2 (process 19492)]
... hmmm

Anyway, the patches (against gdb-7.4.1-3) (phew, the same in sid, so I
haven't been wasting my time.. I forgot to check until now):

--- a/gdb/common/signals.c
+++ b/gdb/common/signals.c
@@ -600,6 +600,15 @@
       return SIGINFO;
 #endif
 
+#if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+    case TARGET_SIGNAL_LINUXTHREADS_RESTART:
+      return 32;
+    case TARGET_SIGNAL_LINUXTHREADS_CANCEL:
+      return 33;
+    case TARGET_SIGNAL_LINUXTHREADS_DEBUG:
+      return 34;
+#endif
+
     default:
 #if defined (REALTIME_LO)
       retsig = 0;
--- a/include/gdb/signals.def
+++ b/include/gdb/signals.def
@@ -194,9 +194,9 @@
 SET (TARGET_EXC_SOFTWARE, 149, "EXC_SOFTWARE", "Software generated exception")
 SET (TARGET_EXC_BREAKPOINT, 150, "EXC_BREAKPOINT", "Breakpoint")
 
-SET (TARGET_SIGNAL_LINUXTHREADS_RESTART, 151, "32", "LinuxThreads restart signal")
-SET (TARGET_SIGNAL_LINUXTHREADS_CANCEL, 152, "33", "LinuxThreads cancel signal")
-SET (TARGET_SIGNAL_LINUXTHREADS_DEBUG, 153, "34", "LinuxThreads debug signal")
+SET (TARGET_SIGNAL_LINUXTHREADS_RESTART, 151, "LTRESTART", "LinuxThreads restart signal")
+SET (TARGET_SIGNAL_LINUXTHREADS_CANCEL, 152, "LTCANCEL", "LinuxThreads cancel signal")
+SET (TARGET_SIGNAL_LINUXTHREADS_DEBUG, 153, "LTDEBUG", "LinuxThreads debug signal")
 
 /* If you are adding a new signal, add it just above this comment.  */
 
--- a/gdb/amd64bsd-nat.c
+++ b/gdb/amd64bsd-nat.c
@@ -35,6 +35,8 @@
 #include "inf-ptrace.h"
 
 
+#define TPIDGET(x) (TIDGET(x) ? TIDGET(x) : PIDGET(x))
+
 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
    for all registers (including the floating-point registers).  */
 
@@ -48,7 +50,7 @@
     {
       struct reg regs;
 
-      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_GETREGS, TPIDGET (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
 	perror_with_name (_("Couldn't get registers"));
 
@@ -61,7 +63,7 @@
     {
       struct fpreg fpregs;
 
-      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_GETFPREGS, TPIDGET (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
 	perror_with_name (_("Couldn't get floating point status"));
 
@@ -82,13 +84,13 @@
     {
       struct reg regs;
 
-      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_GETREGS, TPIDGET (inferior_ptid),
                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
         perror_with_name (_("Couldn't get registers"));
 
       amd64_collect_native_gregset (regcache, &regs, regnum);
 
-      if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_SETREGS, TPIDGET (inferior_ptid),
 	          (PTRACE_TYPE_ARG3) &regs, 0) == -1)
         perror_with_name (_("Couldn't write registers"));
 
@@ -100,13 +102,13 @@
     {
       struct fpreg fpregs;
 
-      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_GETFPREGS, TPIDGET (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
 	perror_with_name (_("Couldn't get floating point status"));
 
       amd64_collect_fxsave (regcache, regnum, &fpregs);
 
-      if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
+      if (ptrace (PT_SETFPREGS, TPIDGET (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
 	perror_with_name (_("Couldn't write floating point status"));
     }
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -25,6 +25,7 @@
 #include "terminal.h"
 #include "gdbcore.h"
 #include "regcache.h"
+#include "ptid.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -36,6 +37,12 @@
 #include "inf-child.h"
 #include "gdbthread.h"
 
+#if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+#define PT_LWPINFO      13      /* Info about the LWP that stopped. */
+#define PT_GETNUMLWPS   14      /* get total number of threads */
+#define PT_GETLWPLIST   15      /* get thread list */
+#endif
+
 
 
 #ifdef PT_GET_PROCESS_STATE
@@ -618,6 +625,28 @@
   return normal_pid_to_str (ptid);
 }
 
+static void
+inf_ptrace_find_new_threads (struct target_ops *ops)
+{
+#ifdef PT_GETLWPLIST
+  int pid = ptid_get_lwp (inferior_ptid), nt;
+  if (pid == 0)
+    pid = ptid_get_pid (inferior_ptid);
+  nt = ptrace(PT_GETNUMLWPS, pid, 0, 0);
+  if(nt < 0) return;
+    {
+      int ti[nt];
+      int i;
+      nt = ptrace(PT_GETLWPLIST, pid, (caddr_t)ti, nt);
+      for(i=0; i<nt; i++) {
+        ptid_t gdb_threadid = MERGEPID (pid, ti[i]);
+        if(!in_thread_list (gdb_threadid) || is_exited (gdb_threadid))
+          add_thread (gdb_threadid);
+    }
+  }
+#endif
+}
+
 /* Create a prototype ptrace target.  The client can override it with
    local methods.  */
 
@@ -643,6 +672,7 @@
   t->to_pid_to_str = inf_ptrace_pid_to_str;
   t->to_stop = inf_ptrace_stop;
   t->to_xfer_partial = inf_ptrace_xfer_partial;
+  t->to_find_new_threads = inf_ptrace_find_new_threads;
 
   return t;
 }


Reply to: