#include <errno.h>
 #include <sys/syscall.h>
 
+#ifndef PTRACE_GETSIGINFO
+# define PTRACE_GETSIGINFO 0x4202
+# define PTRACE_SETSIGINFO 0x4203
+#endif
+
 /* ``all_threads'' is keyed by the LWP ID - it should be the thread ID instead,
    however.  This requires changing the ID in place when we go from !using_threads
    to using_threads, immediately.
 int using_threads;
 
 static void linux_resume_one_process (struct inferior_list_entry *entry,
-                                     int step, int signal);
+                                     int step, int signal, siginfo_t *info);
 static void linux_resume (struct thread_resume *resume_info);
 static void stop_all_processes (void);
 static int linux_wait_for_event (struct thread_info *child);
 struct pending_signals
 {
   int signal;
+  siginfo_t info;
   struct pending_signals *prev;
 };
 
           So instead of reporting the old SIGTRAP, pretend we got to
           the breakpoint just after it was removed instead of just
           before; resume the process.  */
-       linux_resume_one_process (&process->head, 0, 0);
+       linux_resume_one_process (&process->head, 0, 0, NULL);
        return 0;
       }
 
   (*childp)->stopped = 1;
   (*childp)->pending_is_breakpoint = 0;
 
+  (*childp)->last_status = *wstatp;
+
   if (debug_threads
       && WIFSTOPPED (*wstatp))
     {
                fprintf (stderr, "Expected stop.\n");
              event_child->stop_expected = 0;
              linux_resume_one_process (&event_child->head,
-                                       event_child->stepping, 0);
+                                       event_child->stepping, 0, NULL);
              continue;
            }
 
              && (WSTOPSIG (wstat) == __SIGRTMIN
                  || WSTOPSIG (wstat) == __SIGRTMIN + 1))
            {
+             siginfo_t info, *info_p;
+
              if (debug_threads)
                fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
                         WSTOPSIG (wstat), event_child->tid,
                         event_child->head.id);
+
+             if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
+               info_p = &info;
+             else
+               info_p = NULL;
              linux_resume_one_process (&event_child->head,
                                        event_child->stepping,
-                                       WSTOPSIG (wstat));
+                                       WSTOPSIG (wstat), info_p);
              continue;
            }
        }
          event_child->bp_reinsert = 0;
 
          /* Clear the single-stepping flag and SIGTRAP as we resume.  */
-         linux_resume_one_process (&event_child->head, 0, 0);
+         linux_resume_one_process (&event_child->head, 0, 0, NULL);
          continue;
        }
 
            {
              event_child->bp_reinsert = stop_pc;
              uninsert_breakpoint (stop_pc);
-             linux_resume_one_process (&event_child->head, 1, 0);
+             linux_resume_one_process (&event_child->head, 1, 0, NULL);
            }
          else
            {
              reinsert_breakpoint_by_bp
                (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
-             linux_resume_one_process (&event_child->head, 0, 0);
+             linux_resume_one_process (&event_child->head, 0, 0, NULL);
            }
 
          continue;
 
 static void
 linux_resume_one_process (struct inferior_list_entry *entry,
-                         int step, int signal)
+                         int step, int signal, siginfo_t *info)
 {
   struct process_info *process = (struct process_info *) entry;
   struct thread_info *saved_inferior;
       p_sig = malloc (sizeof (*p_sig));
       p_sig->prev = process->pending_signals;
       p_sig->signal = signal;
+      if (info == NULL)
+       memset (&p_sig->info, 0, sizeof (siginfo_t));
+      else
+       memcpy (&p_sig->info, info, sizeof (siginfo_t));
       process->pending_signals = p_sig;
     }
 
        p_sig = &(*p_sig)->prev;
 
       signal = (*p_sig)->signal;
+      if ((*p_sig)->info.si_signo != 0)
+       ptrace (PTRACE_SETSIGINFO, process->lwpid, 0, &(*p_sig)->info);
+
       free (*p_sig);
       *p_sig = NULL;
     }
   else
     step = process->resume->step;
 
-  linux_resume_one_process (&process->head, step, process->resume->sig);
+  linux_resume_one_process (&process->head, step, process->resume->sig, NULL);
 
   process->resume = NULL;
 }
       p_sig = malloc (sizeof (*p_sig));
       p_sig->prev = process->pending_signals;
       p_sig->signal = process->resume->sig;
+      memset (&p_sig->info, 0, sizeof (siginfo_t));
+
+      /* If this is the same signal we were previously stopped by,
+        make sure to queue its siginfo.  We can ignore the return
+        value of ptrace; if it fails, we'll skip
+        PTRACE_SETSIGINFO.  */
+      if (WIFSTOPPED (process->last_status)
+         && WSTOPSIG (process->last_status) == process->resume->sig)
+       ptrace (PTRACE_GETSIGINFO, process->lwpid, 0, &p_sig->info);
+
       process->pending_signals = p_sig;
     }